| Index: vm/snapshot.cc
|
| ===================================================================
|
| --- vm/snapshot.cc (revision 10409)
|
| +++ vm/snapshot.cc (working copy)
|
| @@ -11,37 +11,100 @@
|
| #include "vm/heap.h"
|
| #include "vm/object.h"
|
| #include "vm/object_store.h"
|
| +#include "vm/snapshot_ids.h"
|
| #include "vm/symbols.h"
|
|
|
| namespace dart {
|
|
|
| -enum {
|
| - kInstanceId = ObjectStore::kMaxId,
|
| - kMaxPredefinedObjectIds,
|
| -};
|
| static const int kNumInitialReferencesInFullSnapshot = 160 * KB;
|
| static const int kNumInitialReferences = 4;
|
|
|
|
|
| -static bool IsSingletonClassId(intptr_t index) {
|
| +static bool IsSingletonClassId(intptr_t class_id) {
|
| // Check if this is a singleton object class which is shared by all isolates.
|
| - return (index >= Object::kClassClass && index < Object::kMaxId);
|
| + return ((class_id >= kClassCid && class_id <= kUnwindErrorCid) ||
|
| + (class_id >= kNullCid && class_id <= kVoidCid));
|
| }
|
|
|
|
|
| -static bool IsObjectStoreClassId(intptr_t index) {
|
| +static bool IsObjectStoreClassId(intptr_t class_id) {
|
| // Check if this is a class which is stored in the object store.
|
| - return (index >= ObjectStore::kObjectClass && index < ObjectStore::kMaxId);
|
| + return (class_id == kObjectCid ||
|
| + (class_id >= kInstanceCid && class_id <= kJSRegExpCid));
|
| }
|
|
|
|
|
| static bool IsObjectStoreTypeId(intptr_t index) {
|
| // Check if this is a type which is stored in the object store.
|
| - return (index >= ObjectStore::kObjectType &&
|
| - index <= ObjectStore::kListInterface);
|
| + return (index >= kObjectType && index <= kByteArrayInterface);
|
| }
|
|
|
|
|
| +static intptr_t ClassIdFromObjectId(intptr_t object_id) {
|
| + ASSERT(object_id > kClassIdsOffset);
|
| + intptr_t class_id = (object_id - kClassIdsOffset);
|
| + return class_id;
|
| +}
|
| +
|
| +
|
| +static intptr_t ObjectIdFromClassId(intptr_t class_id) {
|
| + ASSERT(class_id > kIllegalCid && class_id < kNumPredefinedCids);
|
| + return (class_id + kClassIdsOffset);
|
| +}
|
| +
|
| +
|
| +static RawType* GetType(ObjectStore* object_store, int index) {
|
| + switch (index) {
|
| + case kObjectType: return object_store->object_type();
|
| + case kNullType: return object_store->null_type();
|
| + case kDynamicType: return object_store->dynamic_type();
|
| + case kVoidType: return object_store->void_type();
|
| + case kFunctionInterface: return object_store->function_interface();
|
| + case kNumberInterface: return object_store->number_interface();
|
| + case kDoubleInterface: return object_store->double_interface();
|
| + case kIntInterface: return object_store->int_interface();
|
| + case kBoolInterface: return object_store->bool_interface();
|
| + case kStringInterface: return object_store->string_interface();
|
| + case kListInterface: return object_store->list_interface();
|
| + case kByteArrayInterface: return object_store->byte_array_interface();
|
| + default: break;
|
| + }
|
| + UNREACHABLE();
|
| + return Type::null();
|
| +}
|
| +
|
| +
|
| +static int GetTypeIndex(ObjectStore* object_store, const RawType* raw_type) {
|
| + ASSERT(raw_type->IsHeapObject());
|
| + if (raw_type == object_store->object_type()) {
|
| + return kObjectType;
|
| + } else if (raw_type == object_store->null_type()) {
|
| + return kNullType;
|
| + } else if (raw_type == object_store->dynamic_type()) {
|
| + return kDynamicType;
|
| + } else if (raw_type == object_store->void_type()) {
|
| + return kVoidType;
|
| + } else if (raw_type == object_store->function_interface()) {
|
| + return kFunctionInterface;
|
| + } else if (raw_type == object_store->number_interface()) {
|
| + return kNumberInterface;
|
| + } else if (raw_type == object_store->double_interface()) {
|
| + return kDoubleInterface;
|
| + } else if (raw_type == object_store->int_interface()) {
|
| + return kIntInterface;
|
| + } else if (raw_type == object_store->bool_interface()) {
|
| + return kBoolInterface;
|
| + } else if (raw_type == object_store->string_interface()) {
|
| + return kStringInterface;
|
| + } else if (raw_type == object_store->list_interface()) {
|
| + return kListInterface;
|
| + } else if (raw_type == object_store->byte_array_interface()) {
|
| + return kByteArrayInterface;
|
| + }
|
| + return kInvalidIndex;
|
| +}
|
| +
|
| +
|
| // TODO(5411462): Temporary setup of snapshot for testing purposes,
|
| // the actual creation of a snapshot maybe done differently.
|
| const Snapshot* Snapshot::SetupFromBuffer(const void* raw_memory) {
|
| @@ -167,7 +230,7 @@
|
| // Since we are only reading an object reference, If it is an instance kind
|
| // then we only need to figure out the class of the object and allocate an
|
| // instance of it. The individual fields will be read later.
|
| - if (SerializedHeaderData::decode(class_header) == kInstanceId) {
|
| + if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
|
| Instance& result = Instance::ZoneHandle(isolate(), Instance::null());
|
| AddBackRef(object_id, &result, kIsNotDeserialized);
|
|
|
| @@ -181,16 +244,15 @@
|
| result ^= Object::Allocate(cls_.id(), instance_size, Heap::kNew);
|
| }
|
| return result.raw();
|
| - } else {
|
| - ASSERT((class_header & kSmiTagMask) != 0);
|
| - cls_ = LookupInternalClass(class_header);
|
| - ASSERT(!cls_.IsNull());
|
| }
|
| + ASSERT((class_header & kSmiTagMask) != 0);
|
| + cls_ = LookupInternalClass(class_header);
|
| + ASSERT(!cls_.IsNull());
|
|
|
| // Similarly Array and ImmutableArray objects are also similarly only
|
| // allocated here, the individual array elements are read later.
|
| - ObjectKind obj_kind = cls_.instance_kind();
|
| - if (obj_kind == Array::kInstanceKind) {
|
| + intptr_t class_id = cls_.id();
|
| + if (class_id == kArrayCid) {
|
| // Read the length and allocate an object based on the len.
|
| intptr_t len = ReadSmiValue();
|
| Array& array = Array::ZoneHandle(
|
| @@ -200,7 +262,7 @@
|
|
|
| return array.raw();
|
| }
|
| - if (obj_kind == ImmutableArray::kInstanceKind) {
|
| + if (class_id == kImmutableArrayCid) {
|
| // Read the length and allocate an object based on the len.
|
| intptr_t len = ReadSmiValue();
|
| ImmutableArray& array = ImmutableArray::ZoneHandle(
|
| @@ -214,9 +276,9 @@
|
|
|
| // For all other internal VM classes we read the object inline.
|
| intptr_t tags = ReadIntptrValue();
|
| - switch (obj_kind) {
|
| + switch (class_id) {
|
| #define SNAPSHOT_READ(clazz) \
|
| - case clazz::kInstanceKind: { \
|
| + case clazz::kClassId: { \
|
| obj_ = clazz::ReadFrom(this, object_id, tags, kind_); \
|
| break; \
|
| }
|
| @@ -348,28 +410,26 @@
|
| }
|
|
|
|
|
| -RawClass* SnapshotReader::NewClass(int value) {
|
| +RawClass* SnapshotReader::NewClass(intptr_t class_id, bool is_signature_class) {
|
| ASSERT(kind_ == Snapshot::kFull);
|
| ASSERT(isolate()->no_gc_scope_depth() != 0);
|
| - ObjectKind object_kind = static_cast<ObjectKind>(value);
|
| - if ((object_kind == kInstance || object_kind == kClosure)) {
|
| - cls_ = Object::class_class();
|
| - RawClass* obj = reinterpret_cast<RawClass*>(
|
| - AllocateUninitialized(cls_, Class::InstanceSize()));
|
| - if (object_kind == kInstance) {
|
| - Instance fake;
|
| - obj->ptr()->handle_vtable_ = fake.vtable();
|
| - } else {
|
| - Closure fake;
|
| - obj->ptr()->handle_vtable_ = fake.vtable();
|
| - }
|
| - cls_ = obj;
|
| - cls_.set_instance_kind(object_kind);
|
| - cls_.set_id(kIllegalObjectKind);
|
| - isolate()->class_table()->Register(cls_);
|
| - return cls_.raw();
|
| + if (class_id < kNumPredefinedCids) {
|
| + return Class::GetClass(class_id, is_signature_class);
|
| }
|
| - return Class::GetClass(object_kind);
|
| + cls_ = Object::class_class();
|
| + RawClass* obj = reinterpret_cast<RawClass*>(
|
| + AllocateUninitialized(cls_, Class::InstanceSize()));
|
| + if (is_signature_class) {
|
| + Closure fake;
|
| + obj->ptr()->handle_vtable_ = fake.vtable();
|
| + } else {
|
| + Instance fake;
|
| + obj->ptr()->handle_vtable_ = fake.vtable();
|
| + }
|
| + cls_ = obj;
|
| + cls_.set_id(kIllegalCid);
|
| + isolate()->class_table()->Register(cls_);
|
| + return cls_.raw();
|
| }
|
|
|
|
|
| @@ -474,12 +534,12 @@
|
| if (IsVMIsolateObject(class_header)) {
|
| intptr_t class_id = GetVMIsolateObjectId(class_header);
|
| if (IsSingletonClassId(class_id)) {
|
| - return Object::GetSingletonClass(class_id); // return singleton.
|
| + return isolate()->class_table()->At(class_id); // get singleton class.
|
| }
|
| } else if (SerializedHeaderTag::decode(class_header) == kObjectId) {
|
| - intptr_t header_value = SerializedHeaderData::decode(class_header);
|
| - if (IsObjectStoreClassId(header_value)) {
|
| - return object_store()->GetClass(header_value);
|
| + intptr_t class_id = SerializedHeaderData::decode(class_header);
|
| + if (IsObjectStoreClassId(class_id)) {
|
| + return isolate()->class_table()->At(class_id); // get singleton class.
|
| }
|
| }
|
| return Class::null();
|
| @@ -504,7 +564,7 @@
|
| RawObject* raw_obj = reinterpret_cast<RawObject*>(address + kHeapObjectTag);
|
| uword tags = 0;
|
| intptr_t index = cls.id();
|
| - ASSERT(index != kIllegalObjectKind);
|
| + ASSERT(index != kIllegalCid);
|
| tags = RawObject::ClassIdTag::update(index, tags);
|
| tags = RawObject::SizeTag::update(size, tags);
|
| raw_obj->ptr()->tags_ = tags;
|
| @@ -514,36 +574,41 @@
|
|
|
| RawObject* SnapshotReader::ReadVMIsolateObject(intptr_t header_value) {
|
| intptr_t object_id = GetVMIsolateObjectId(header_value);
|
| - if (object_id == Object::kNullObject) {
|
| + if (object_id == kNullObject) {
|
| // This is a singleton null object, return it.
|
| return Object::null();
|
| }
|
| - if (object_id == Object::kSentinelObject) {
|
| + if (object_id == kSentinelObject) {
|
| return Object::sentinel();
|
| }
|
| - if (IsSingletonClassId(object_id)) {
|
| - return Object::GetSingletonClass(object_id); // return singleton object.
|
| + intptr_t class_id = ClassIdFromObjectId(object_id);
|
| + if (IsSingletonClassId(class_id)) {
|
| + return isolate()->class_table()->At(class_id); // get singleton class.
|
| } else {
|
| ASSERT(Symbols::IsVMSymbolId(object_id));
|
| return Symbols::GetVMSymbol(object_id); // return VM symbol.
|
| }
|
| UNREACHABLE();
|
| + return Object::null();
|
| }
|
|
|
|
|
| RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) {
|
| - if (IsObjectStoreClassId(object_id)) {
|
| - return object_store()->GetClass(object_id);
|
| - } else if (object_id == ObjectStore::kTrueValue) {
|
| + if (object_id == kTrueValue) {
|
| return object_store()->true_value();
|
| - } else if (object_id == ObjectStore::kFalseValue) {
|
| + }
|
| + if (object_id == kFalseValue) {
|
| return object_store()->false_value();
|
| - } else if (kind_ != Snapshot::kFull) {
|
| + }
|
| + intptr_t class_id = ClassIdFromObjectId(object_id);
|
| + if (IsObjectStoreClassId(class_id)) {
|
| + return isolate()->class_table()->At(class_id); // get singleton class.
|
| + }
|
| + if (kind_ != Snapshot::kFull) {
|
| if (IsObjectStoreTypeId(object_id)) {
|
| - return object_store()->GetType(object_id); // return type object.
|
| + return GetType(object_store(), object_id); // return type obj.
|
| }
|
| }
|
| -
|
| Object* object = GetBackRef(object_id);
|
| return object->raw();
|
| }
|
| @@ -553,7 +618,7 @@
|
| // Read the class header information and lookup the class.
|
| intptr_t class_header = ReadIntptrValue();
|
| intptr_t tags = ReadIntptrValue();
|
| - if (SerializedHeaderData::decode(class_header) == kInstanceId) {
|
| + if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
|
| // Object is regular dart instance.
|
| Instance* result = reinterpret_cast<Instance*>(GetBackRef(object_id));
|
| intptr_t instance_size = 0;
|
| @@ -587,14 +652,13 @@
|
| *result = result->Canonicalize();
|
| }
|
| return result->raw();
|
| - } else {
|
| - ASSERT((class_header & kSmiTagMask) != 0);
|
| - cls_ = LookupInternalClass(class_header);
|
| - ASSERT(!cls_.IsNull());
|
| }
|
| - switch (cls_.instance_kind()) {
|
| + ASSERT((class_header & kSmiTagMask) != 0);
|
| + cls_ = LookupInternalClass(class_header);
|
| + ASSERT(!cls_.IsNull());
|
| + switch (cls_.id()) {
|
| #define SNAPSHOT_READ(clazz) \
|
| - case clazz::kInstanceKind: { \
|
| + case clazz::kClassId: { \
|
| obj_ = clazz::ReadFrom(this, object_id, tags, kind_); \
|
| break; \
|
| }
|
| @@ -635,28 +699,33 @@
|
| void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
|
| // Check if it is a singleton null object.
|
| if (rawobj == Object::null()) {
|
| - WriteVMIsolateObject(Object::kNullObject);
|
| + WriteVMIsolateObject(kNullObject);
|
| return;
|
| }
|
|
|
| // Check if it is a singleton sentinel object.
|
| if (rawobj == Object::sentinel()) {
|
| - WriteVMIsolateObject(Object::kSentinelObject);
|
| + WriteVMIsolateObject(kSentinelObject);
|
| return;
|
| }
|
|
|
| - // Check if it is a singleton class object.
|
| - RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj);
|
| - intptr_t index = Object::GetSingletonClassIndex(raw_class);
|
| - if (index != Object::kInvalidIndex) {
|
| - WriteVMIsolateObject(index);
|
| - return;
|
| + // Check if it is a singleton class object which is shared by
|
| + // all isolates.
|
| + intptr_t id = rawobj->GetClassId();
|
| + if (id == kClassCid) {
|
| + RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj);
|
| + intptr_t class_id = raw_class->ptr()->id_;
|
| + if (IsSingletonClassId(class_id)) {
|
| + intptr_t object_id = ObjectIdFromClassId(class_id);
|
| + WriteVMIsolateObject(object_id);
|
| + return;
|
| + }
|
| }
|
|
|
| - // Check it is a predefined symbol.
|
| - index = Symbols::LookupVMSymbol(rawobj);
|
| - if (index != Object::kInvalidIndex) {
|
| - WriteVMIsolateObject(index);
|
| + // Check it is a predefined symbol in the VM isolate.
|
| + id = Symbols::LookupVMSymbol(rawobj);
|
| + if (id != kInvalidIndex) {
|
| + WriteVMIsolateObject(id);
|
| return;
|
| }
|
|
|
| @@ -669,20 +738,13 @@
|
| if (CheckAndWritePredefinedObject(raw)) {
|
| return;
|
| }
|
| - // Check if object has already been serialized, in that
|
| - // case just write the object id out.
|
| - uword tags = raw->ptr()->tags_;
|
| - if (SerializedHeaderTag::decode(tags) == kObjectId) {
|
| - intptr_t id = SerializedHeaderData::decode(tags);
|
| - WriteIndexedObject(id);
|
| - return;
|
| - }
|
|
|
| NoGCScope no_gc;
|
| - RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
|
| -
|
| - ObjectKind obj_kind = cls->ptr()->instance_kind_;
|
| - if (obj_kind == Instance::kInstanceKind) {
|
| + RawClass* cls = class_table_->At(raw->GetClassId());
|
| + intptr_t class_id = cls->ptr()->id_;
|
| + ASSERT(class_id == raw->GetClassId());
|
| + if (class_id >= kNumPredefinedCids) {
|
| + ASSERT(!Class::IsSignatureClass(cls));
|
| // Object is being referenced, add it to the forward ref list and mark
|
| // it so that future references to this object in the snapshot will use
|
| // this object id. Mark it as not having been serialized yet so that we
|
| @@ -693,14 +755,14 @@
|
| WriteInlinedObjectHeader(object_id);
|
|
|
| // Indicate this is an instance object.
|
| - WriteIntptrValue(SerializedHeaderData::encode(kInstanceId));
|
| + WriteIntptrValue(SerializedHeaderData::encode(kInstanceObjectId));
|
|
|
| // Write out the class information for this object.
|
| WriteObjectImpl(cls);
|
|
|
| return;
|
| }
|
| - if (obj_kind == Array::kInstanceKind) {
|
| + if (class_id == kArrayCid) {
|
| // Object is being referenced, add it to the forward ref list and mark
|
| // it so that future references to this object in the snapshot will use
|
| // this object id. Mark it as not having been serialized yet so that we
|
| @@ -713,14 +775,14 @@
|
| WriteInlinedObjectHeader(object_id);
|
|
|
| // Write out the class information.
|
| - WriteIndexedObject(ObjectStore::kArrayClass);
|
| + WriteIndexedObject(kArrayCid);
|
|
|
| // Write out the length field.
|
| Write<RawObject*>(rawarray->ptr()->length_);
|
|
|
| return;
|
| }
|
| - if (obj_kind == ImmutableArray::kInstanceKind) {
|
| + if (class_id == kImmutableArrayCid) {
|
| // Object is being referenced, add it to the forward ref list and mark
|
| // it so that future references to this object in the snapshot will use
|
| // this object id. Mark it as not having been serialized yet so that we
|
| @@ -733,7 +795,7 @@
|
| WriteInlinedObjectHeader(object_id);
|
|
|
| // Write out the class information.
|
| - WriteIndexedObject(ObjectStore::kImmutableArrayClass);
|
| + WriteIndexedObject(kImmutableArrayCid);
|
|
|
| // Write out the length field.
|
| Write<RawObject*>(rawarray->ptr()->length_);
|
| @@ -745,9 +807,9 @@
|
| // this object id. Mark it as not having been serialized yet so that we
|
| // will serialize the object when we go through the forward list.
|
| intptr_t object_id = MarkObject(raw, kIsSerialized);
|
| - switch (obj_kind) {
|
| + switch (class_id) {
|
| #define SNAPSHOT_WRITE(clazz) \
|
| - case clazz::kInstanceKind: { \
|
| + case clazz::kClassId: { \
|
| Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \
|
| raw_obj->WriteTo(this, object_id, kind_); \
|
| return; \
|
| @@ -850,28 +912,28 @@
|
|
|
| // Check if it is a singleton boolean true value.
|
| if (rawobj == object_store()->true_value()) {
|
| - WriteIndexedObject(ObjectStore::kTrueValue);
|
| + WriteIndexedObject(kTrueValue);
|
| return true;
|
| }
|
|
|
| // Check if it is a singleton boolean false value.
|
| if (rawobj == object_store()->false_value()) {
|
| - WriteIndexedObject(ObjectStore::kFalseValue);
|
| + WriteIndexedObject(kFalseValue);
|
| return true;
|
| }
|
|
|
| // Check if it is a code object in that case just write a Null object
|
| // as we do not want code objects in the snapshot.
|
| - if (rawobj->GetClassId() == kCode) {
|
| - WriteVMIsolateObject(Object::kNullObject);
|
| + if (rawobj->GetClassId() == kCodeCid) {
|
| + WriteVMIsolateObject(kNullObject);
|
| return true;
|
| }
|
|
|
| // Check if classes are not being serialized and it is preinitialized type.
|
| if (kind_ != Snapshot::kFull) {
|
| RawType* raw_type = reinterpret_cast<RawType*>(rawobj);
|
| - intptr_t index = object_store()->GetTypeIndex(raw_type);
|
| - if (index != ObjectStore::kInvalidIndex) {
|
| + intptr_t index = GetTypeIndex(object_store(), raw_type);
|
| + if (index != kInvalidIndex) {
|
| WriteIndexedObject(index);
|
| return true;
|
| }
|
| @@ -908,9 +970,10 @@
|
| intptr_t object_id = SerializedHeaderData::decode(tags);
|
| tags = forward_list_[object_id - kMaxPredefinedObjectIds]->tags();
|
| RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
|
| - ObjectKind kind = cls->ptr()->instance_kind_;
|
| + intptr_t class_id = cls->ptr()->id_;
|
|
|
| - if (kind == Instance::kInstanceKind) {
|
| + if (class_id >= kNumPredefinedCids) {
|
| + ASSERT(!Class::IsSignatureClass(cls));
|
| // Object is regular dart instance.
|
| // TODO(5411462): figure out what we need to do if an object with native
|
| // fields is serialized (throw exception or serialize a null object).
|
| @@ -922,7 +985,7 @@
|
| WriteInlinedObjectHeader(object_id);
|
|
|
| // Indicate this is an instance object.
|
| - WriteIntptrValue(SerializedHeaderData::encode(kInstanceId));
|
| + WriteIntptrValue(SerializedHeaderData::encode(kInstanceObjectId));
|
|
|
| // Write out the tags.
|
| WriteIntptrValue(tags);
|
| @@ -939,9 +1002,9 @@
|
| }
|
| return;
|
| }
|
| - switch (kind) {
|
| + switch (class_id) {
|
| #define SNAPSHOT_WRITE(clazz) \
|
| - case clazz::kInstanceKind: { \
|
| + case clazz::kClassId: { \
|
| Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \
|
| raw_obj->WriteTo(this, object_id, kind_); \
|
| return; \
|
| @@ -976,16 +1039,18 @@
|
|
|
| void SnapshotWriter::WriteClassId(RawClass* cls) {
|
| ASSERT(kind_ != Snapshot::kFull);
|
| - int id = object_store()->GetClassIndex(cls);
|
| - if (IsSingletonClassId(id)) {
|
| - WriteVMIsolateObject(id);
|
| - } else if (IsObjectStoreClassId(id)) {
|
| - WriteIndexedObject(id);
|
| + int class_id = cls->ptr()->id_;
|
| + if (IsSingletonClassId(class_id)) {
|
| + intptr_t object_id = ObjectIdFromClassId(class_id);
|
| + WriteVMIsolateObject(object_id);
|
| + } else if (IsObjectStoreClassId(class_id)) {
|
| + intptr_t object_id = ObjectIdFromClassId(class_id);
|
| + WriteIndexedObject(object_id);
|
| } else {
|
| // TODO(5411462): Should restrict this to only core-lib classes in this
|
| // case.
|
| // Write out the class and tags information.
|
| - WriteVMIsolateObject(Object::kClassClass);
|
| + WriteVMIsolateObject(kClassCid);
|
| WriteIntptrValue(GetObjectTags(cls));
|
|
|
| // Write out the library url and class name.
|
|
|