| Index: runtime/vm/isolate_reload.h
|
| diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
|
| index 8d0c5934304e20dc576056f35da0a602522a7833..ce316f6dd2e61a33a1bbf9898964b819892f6639 100644
|
| --- a/runtime/vm/isolate_reload.h
|
| +++ b/runtime/vm/isolate_reload.h
|
| @@ -5,6 +5,7 @@
|
| #ifndef VM_ISOLATE_RELOAD_H_
|
| #define VM_ISOLATE_RELOAD_H_
|
|
|
| +#include "vm/hash_map.h"
|
| #include "vm/globals.h"
|
| #include "vm/growable_array.h"
|
| #include "vm/log.h"
|
| @@ -44,6 +45,77 @@ class ObjectPointerVisitor;
|
| class ObjectStore;
|
| class UpdateClassesVisitor;
|
|
|
| +
|
| +class InstanceMorpher : public ZoneAllocated {
|
| + public:
|
| + InstanceMorpher(const Class& from, const Class& to);
|
| + virtual ~InstanceMorpher() {}
|
| +
|
| + // Called on each instance that needs to be morphed.
|
| + RawInstance* Morph(const Instance& instance) const;
|
| +
|
| + // Adds an object to be morphed.
|
| + void AddObject(RawObject* object) const;
|
| +
|
| + // Create the morphed objects based on the before() list.
|
| + void CreateMorphedCopies() const;
|
| +
|
| + // Dump the state of the morpher.
|
| + void Dump() const;
|
| +
|
| + // Returns the list of objects that need to be morphed.
|
| + ZoneGrowableArray<const Instance*>* before() const { return before_; }
|
| + // Returns the list of morphed objects (matches order in before()).
|
| + ZoneGrowableArray<const Instance*>* after() const { return after_; }
|
| +
|
| + // Returns the cid associated with the from_ and to_ class.
|
| + intptr_t cid() const { return cid_; }
|
| +
|
| + private:
|
| + const Class& from_;
|
| + const Class& to_;
|
| + ZoneGrowableArray<intptr_t> mapping_;
|
| + ZoneGrowableArray<const Instance*>* before_;
|
| + ZoneGrowableArray<const Instance*>* after_;
|
| + intptr_t cid_;
|
| +
|
| + void ComputeMapping();
|
| + void DumpFormatFor(const Class& cls) const;
|
| +};
|
| +
|
| +
|
| +class ReasonForCancelling : public ZoneAllocated {
|
| + public:
|
| + ReasonForCancelling() {}
|
| + virtual ~ReasonForCancelling() {}
|
| +
|
| + // Reports a reason for cancelling reload.
|
| + void Report(IsolateReloadContext* context);
|
| +
|
| + // Conversion to a VM error object.
|
| + // Default implementation calls ToString.
|
| + virtual RawError* ToError();
|
| +
|
| + // Conversion to a string object.
|
| + // Default implementation calls ToError.
|
| + virtual RawString* ToString();
|
| +
|
| + // Concrete subclasses must override either ToError or ToString.
|
| +};
|
| +
|
| +
|
| +// Abstract class for also capturing the from_ and to_ class.
|
| +class ClassReasonForCancelling : public ReasonForCancelling {
|
| + public:
|
| + ClassReasonForCancelling(const Class& from, const Class& to)
|
| + : from_(from), to_(to) { }
|
| +
|
| + protected:
|
| + const Class& from_;
|
| + const Class& to_;
|
| +};
|
| +
|
| +
|
| class IsolateReloadContext {
|
| public:
|
| explicit IsolateReloadContext(Isolate* isolate);
|
| @@ -57,12 +129,12 @@ class IsolateReloadContext {
|
|
|
| RawGrowableObjectArray* saved_libraries() const;
|
|
|
| + // Report back through the observatory channels.
|
| void ReportError(const Error& error);
|
| - void ReportError(const String& error_msg);
|
| void ReportSuccess();
|
|
|
| - bool has_error() const { return has_error_; }
|
| - RawError* error() const { return error_; }
|
| + bool has_error() const { return HasReasonsForCancelling(); }
|
| + RawError* error() const;
|
|
|
| static bool IsSameField(const Field& a, const Field& b);
|
| static bool IsSameLibrary(const Library& a_lib, const Library& b_lib);
|
| @@ -83,6 +155,25 @@ class IsolateReloadContext {
|
|
|
| int64_t start_time_micros() const { return start_time_micros_; }
|
|
|
| + // Tells whether there are reasons for cancelling the reload.
|
| + bool HasReasonsForCancelling() const {
|
| + return !reasons_to_cancel_reload_.is_empty();
|
| + }
|
| +
|
| + // Record problem for this reload.
|
| + void AddReasonForCancelling(ReasonForCancelling* reason);
|
| +
|
| + // Report all reasons for cancelling reload.
|
| + void ReportReasonsForCancelling();
|
| +
|
| + // Store morphing operation.
|
| + void AddInstanceMorpher(InstanceMorpher* morpher);
|
| +
|
| + // Tells whether instance in the heap must be morphed.
|
| + bool HasInstanceMorphers() const {
|
| + return !instance_morphers_.is_empty();
|
| + }
|
| +
|
| private:
|
| void set_saved_root_library(const Library& value);
|
|
|
| @@ -104,6 +195,9 @@ class IsolateReloadContext {
|
| bool IsCleanLibrary(const Library& lib);
|
| void CheckpointLibraries();
|
|
|
| + // Transforms the heap based on instance_morphers_.
|
| + void MorphInstances();
|
| +
|
| bool ValidateReload();
|
|
|
| void Rollback();
|
| @@ -129,12 +223,32 @@ class IsolateReloadContext {
|
|
|
| int64_t start_time_micros_;
|
| Isolate* isolate_;
|
| - bool has_error_;
|
|
|
| intptr_t saved_num_cids_;
|
| RawClass** saved_class_table_;
|
| -
|
| intptr_t num_saved_libs_;
|
| +
|
| + // Collect the necessary instance transformation for schema changes.
|
| + ZoneGrowableArray<InstanceMorpher*> instance_morphers_;
|
| +
|
| + // Collects the reasons for cancelling the reload.
|
| + ZoneGrowableArray<ReasonForCancelling*> reasons_to_cancel_reload_;
|
| +
|
| + // Required trait for the cid_mapper_;
|
| + struct MorpherTrait {
|
| + typedef InstanceMorpher* Value;
|
| + typedef intptr_t Key;
|
| + typedef InstanceMorpher* Pair;
|
| +
|
| + static Key KeyOf(Pair kv) { return kv->cid(); }
|
| + static Value ValueOf(Pair kv) { return kv; }
|
| + static intptr_t Hashcode(Key key) { return key; }
|
| + static bool IsKeyEqual(Pair kv, Key key) { return kv->cid() == key; }
|
| + };
|
| +
|
| + // Hash map from cid to InstanceMorpher.
|
| + DirectChainedHashMap<MorpherTrait> cid_mapper_;
|
| +
|
| struct LibraryInfo {
|
| bool dirty;
|
| };
|
| @@ -176,6 +290,7 @@ class IsolateReloadContext {
|
|
|
| friend class Isolate;
|
| friend class Class; // AddStaticFieldMapping, AddEnumBecomeMapping.
|
| + friend class ObjectLocator;
|
| };
|
|
|
| } // namespace dart
|
|
|