| Index: runtime/vm/snapshot.cc
|
| diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
|
| index 391c9fc14e10c746c886084654300493d496eba4..f56780a5d197478753de3388ad742cc61a530ff3 100644
|
| --- a/runtime/vm/snapshot.cc
|
| +++ b/runtime/vm/snapshot.cc
|
| @@ -206,10 +206,11 @@ RawObject* SnapshotReader::ReadObject() {
|
| // Setup for long jump in case there is an exception while reading.
|
| LongJumpScope jump;
|
| if (setjmp(*jump.Set()) == 0) {
|
| - PassiveObject& obj = PassiveObject::Handle(isolate(), ReadObjectImpl());
|
| + PassiveObject& obj =
|
| + PassiveObject::Handle(isolate(), ReadObjectImpl(kAsInlinedObject));
|
| for (intptr_t i = 0; i < backward_references_->length(); i++) {
|
| if (!(*backward_references_)[i].is_deserialized()) {
|
| - ReadObjectImpl();
|
| + ReadObjectImpl(kAsInlinedObject);
|
| (*backward_references_)[i].set_state(kIsDeserialized);
|
| }
|
| }
|
| @@ -235,12 +236,12 @@ RawClass* SnapshotReader::ReadClassId(intptr_t object_id) {
|
| Class& cls = Class::ZoneHandle(zone(), Class::null());
|
| AddBackRef(object_id, &cls, kIsDeserialized);
|
| // Read the library/class information and lookup the class.
|
| - str_ ^= ReadObjectImpl(class_header);
|
| + str_ ^= ReadObjectImpl(class_header, kAsInlinedObject);
|
| library_ = Library::LookupLibrary(str_);
|
| if (library_.IsNull() || !library_.Loaded()) {
|
| SetReadException("Invalid object found in message.");
|
| }
|
| - str_ ^= ReadObjectImpl();
|
| + str_ ^= ReadObjectImpl(kAsInlinedObject);
|
| cls = library_.LookupClass(str_);
|
| if (cls.IsNull()) {
|
| SetReadException("Invalid object found in message.");
|
| @@ -261,14 +262,14 @@ RawObject* SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id,
|
| AddBackRef(object_id, &obj, kIsDeserialized);
|
|
|
| // Read the library/class/function information and lookup the function.
|
| - str_ ^= ReadObjectImpl();
|
| + str_ ^= ReadObjectImpl(kAsInlinedObject);
|
| library_ = Library::LookupLibrary(str_);
|
| if (library_.IsNull() || !library_.Loaded()) {
|
| SetReadException("Invalid Library object found in message.");
|
| }
|
| - str_ ^= ReadObjectImpl();
|
| + str_ ^= ReadObjectImpl(kAsInlinedObject);
|
| if (str_.Equals(Symbols::TopLevel())) {
|
| - str_ ^= ReadObjectImpl();
|
| + str_ ^= ReadObjectImpl(kAsInlinedObject);
|
| func = library_.LookupFunctionAllowPrivate(str_);
|
| } else {
|
| cls_ = library_.LookupClassAllowPrivate(str_);
|
| @@ -277,7 +278,7 @@ RawObject* SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id,
|
| SetReadException("Invalid Class object found in message.");
|
| }
|
| cls_.EnsureIsFinalized(isolate());
|
| - str_ ^= ReadObjectImpl();
|
| + str_ ^= ReadObjectImpl(kAsInlinedObject);
|
| func = cls_.LookupFunctionAllowPrivate(str_);
|
| }
|
| if (func.IsNull()) {
|
| @@ -292,16 +293,6 @@ RawObject* SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id,
|
| }
|
|
|
|
|
| -RawObject* SnapshotReader::ReadObjectImpl() {
|
| - int64_t value = Read<int64_t>();
|
| - if ((value & kSmiTagMask) == kSmiTag) {
|
| - return NewInteger(value);
|
| - }
|
| - ASSERT((value <= kIntptrMax) && (value >= kIntptrMin));
|
| - return ReadObjectImpl(static_cast<intptr_t>(value));
|
| -}
|
| -
|
| -
|
| intptr_t SnapshotReader::NextAvailableObjectId() const {
|
| return backward_references_->length() +
|
| kMaxPredefinedObjectIds + max_vm_isolate_object_id_;
|
| @@ -331,7 +322,18 @@ RawObject* SnapshotReader::VmIsolateSnapshotObject(intptr_t index) const {
|
| }
|
|
|
|
|
| -RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value) {
|
| +RawObject* SnapshotReader::ReadObjectImpl(bool as_reference) {
|
| + int64_t header_value = Read<int64_t>();
|
| + if ((header_value & kSmiTagMask) == kSmiTag) {
|
| + return NewInteger(header_value);
|
| + }
|
| + ASSERT((header_value <= kIntptrMax) && (header_value >= kIntptrMin));
|
| + return ReadObjectImpl(static_cast<intptr_t>(header_value), as_reference);
|
| +}
|
| +
|
| +
|
| +RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value,
|
| + bool as_reference) {
|
| if (IsVMIsolateObject(header_value)) {
|
| return ReadVMIsolateObject(header_value);
|
| } else {
|
| @@ -343,33 +345,22 @@ RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value) {
|
| if (object_id == kOmittedObjectId) {
|
| object_id = NextAvailableObjectId();
|
| }
|
| - return ReadInlinedObject(object_id);
|
| - }
|
| -}
|
| -
|
|
|
| -RawObject* SnapshotReader::ReadObjectRef() {
|
| - int64_t header_value = Read<int64_t>();
|
| - if ((header_value & kSmiTagMask) == kSmiTag) {
|
| - return NewInteger(header_value);
|
| - }
|
| - ASSERT((header_value <= kIntptrMax) && (header_value >= kIntptrMin));
|
| - intptr_t value = static_cast<intptr_t>(header_value);
|
| - if (IsVMIsolateObject(value)) {
|
| - return ReadVMIsolateObject(value);
|
| - } else if (SerializedHeaderTag::decode(value) == kObjectId) {
|
| - return ReadIndexedObject(SerializedHeaderData::decode(value));
|
| - }
|
| - ASSERT(SerializedHeaderTag::decode(value) == kInlined);
|
| - intptr_t object_id = SerializedHeaderData::decode(value);
|
| - if (object_id == kOmittedObjectId) {
|
| - object_id = NextAvailableObjectId();
|
| + // Read the class header information.
|
| + intptr_t class_header = Read<int32_t>();
|
| + intptr_t tags = ReadTags();
|
| + if (as_reference && !RawObject::IsCanonical(tags)) {
|
| + return ReadObjectRef(object_id, class_header, tags);
|
| + } else {
|
| + return ReadInlinedObject(object_id, class_header, tags);
|
| + }
|
| }
|
| - ASSERT(GetBackRef(object_id) == NULL);
|
| +}
|
|
|
| - // Read the class header information and lookup the class.
|
| - intptr_t class_header = Read<int32_t>();
|
|
|
| +RawObject* SnapshotReader::ReadObjectRef(intptr_t object_id,
|
| + intptr_t class_header,
|
| + intptr_t tags) {
|
| // 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.
|
| @@ -378,7 +369,7 @@ RawObject* SnapshotReader::ReadObjectRef() {
|
| Instance& result = Instance::ZoneHandle(zone(), Instance::null());
|
| AddBackRef(object_id, &result, kIsNotDeserialized);
|
|
|
| - cls_ ^= ReadObjectImpl(); // Read class information.
|
| + cls_ ^= ReadObjectImpl(kAsInlinedObject); // Read class information.
|
| ASSERT(!cls_.IsNull());
|
| intptr_t instance_size = cls_.instance_size();
|
| ASSERT(instance_size > 0);
|
| @@ -392,7 +383,6 @@ RawObject* SnapshotReader::ReadObjectRef() {
|
| // We skip the tags that have been written as the implicit static
|
| // closure is going to be created in this isolate or the canonical
|
| // version already created in the isolate will be used.
|
| - ReadTags();
|
| return ReadStaticImplicitClosure(object_id, class_header);
|
| }
|
| ASSERT((class_header & kSmiTagMask) != kSmiTag);
|
| @@ -424,7 +414,119 @@ RawObject* SnapshotReader::ReadObjectRef() {
|
| }
|
|
|
| // For all other internal VM classes we read the object inline.
|
| - intptr_t tags = ReadTags();
|
| + switch (class_id) {
|
| +#define SNAPSHOT_READ(clazz) \
|
| + case clazz::kClassId: { \
|
| + pobj_ = clazz::ReadFrom(this, object_id, tags, kind_); \
|
| + break; \
|
| + }
|
| + CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
|
| +#undef SNAPSHOT_READ
|
| +#define SNAPSHOT_READ(clazz) \
|
| + case kTypedData##clazz##Cid: \
|
| +
|
| + CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
|
| + tags = RawObject::ClassIdTag::update(class_id, tags);
|
| + pobj_ = TypedData::ReadFrom(this, object_id, tags, kind_);
|
| + break;
|
| + }
|
| +#undef SNAPSHOT_READ
|
| +#define SNAPSHOT_READ(clazz) \
|
| + case kExternalTypedData##clazz##Cid: \
|
| +
|
| + CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
|
| + tags = RawObject::ClassIdTag::update(class_id, tags);
|
| + pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_);
|
| + break;
|
| + }
|
| +#undef SNAPSHOT_READ
|
| + default: UNREACHABLE(); break;
|
| + }
|
| + if (kind_ == Snapshot::kFull) {
|
| + pobj_.SetCreatedFromSnapshot();
|
| + }
|
| + return pobj_.raw();
|
| +}
|
| +
|
| +
|
| +RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id,
|
| + intptr_t class_header,
|
| + intptr_t tags) {
|
| + // Lookup the class based on the class header information.
|
| + intptr_t header_id = SerializedHeaderData::decode(class_header);
|
| + if (header_id == kInstanceObjectId) {
|
| + // Object is regular dart instance.
|
| + Instance* result = reinterpret_cast<Instance*>(GetBackRef(object_id));
|
| + intptr_t instance_size = 0;
|
| + if (result == NULL) {
|
| + result = &(Instance::ZoneHandle(zone(), Instance::null()));
|
| + AddBackRef(object_id, result, kIsDeserialized);
|
| + cls_ ^= ReadObjectImpl(kAsInlinedObject);
|
| + ASSERT(!cls_.IsNull());
|
| + instance_size = cls_.instance_size();
|
| + ASSERT(instance_size > 0);
|
| + // Allocate the instance and read in all the fields for the object.
|
| + if (kind_ == Snapshot::kFull) {
|
| + *result ^= AllocateUninitialized(cls_.id(), instance_size);
|
| + } else {
|
| + *result ^= Object::Allocate(cls_.id(),
|
| + instance_size,
|
| + HEAP_SPACE(kind_));
|
| + }
|
| + } else {
|
| + cls_ ^= ReadObjectImpl(kAsInlinedObject);
|
| + ASSERT(!cls_.IsNull());
|
| + instance_size = cls_.instance_size();
|
| + }
|
| + intptr_t next_field_offset = cls_.next_field_offset();
|
| + intptr_t type_argument_field_offset = cls_.type_arguments_field_offset();
|
| + ASSERT(next_field_offset > 0);
|
| + // Instance::NextFieldOffset() returns the offset of the first field in
|
| + // a Dart object.
|
| + bool as_reference = RawObject::IsCanonical(tags) ? false : true;
|
| + intptr_t offset = Instance::NextFieldOffset();
|
| + intptr_t result_cid = result->GetClassId();
|
| + while (offset < next_field_offset) {
|
| + pobj_ = ReadObjectImpl(as_reference);
|
| + result->SetFieldAtOffset(offset, pobj_);
|
| + if ((offset != type_argument_field_offset) &&
|
| + (kind_ == Snapshot::kMessage)) {
|
| + // TODO(fschneider): Consider hoisting these lookups out of the loop.
|
| + // This would involve creating a handle, since cls_ can't be reused
|
| + // across the call to ReadObjectRef.
|
| + cls_ = isolate()->class_table()->At(result_cid);
|
| + array_ = cls_.OffsetToFieldMap();
|
| + field_ ^= array_.At(offset >> kWordSizeLog2);
|
| + ASSERT(!field_.IsNull());
|
| + ASSERT(field_.Offset() == offset);
|
| + obj_ = pobj_.raw();
|
| + field_.RecordStore(obj_);
|
| + }
|
| + // TODO(fschneider): Verify the guarded cid and length for other kinds of
|
| + // snapshot (kFull, kScript) with asserts.
|
| + offset += kWordSize;
|
| + }
|
| + if (kind_ == Snapshot::kFull) {
|
| + // We create an uninitialized object in the case of full snapshots, so
|
| + // we need to initialize any remaining padding area with the Null object.
|
| + while (offset < instance_size) {
|
| + result->SetFieldAtOffset(offset, Object::null_object());
|
| + offset += kWordSize;
|
| + }
|
| + result->SetCreatedFromSnapshot();
|
| + } else if (RawObject::IsCanonical(tags)) {
|
| + *result = result->CheckAndCanonicalize(NULL);
|
| + ASSERT(!result->IsNull());
|
| + }
|
| + return result->raw();
|
| + } else if (header_id == kStaticImplicitClosureObjectId) {
|
| + // We do not use the tags as the implicit static closure
|
| + // is going to be created in this isolate or the canonical
|
| + // version already created in the isolate will be used.
|
| + return ReadStaticImplicitClosure(object_id, class_header);
|
| + }
|
| + ASSERT((class_header & kSmiTagMask) != kSmiTag);
|
| + intptr_t class_id = LookupInternalClass(class_header);
|
| switch (class_id) {
|
| #define SNAPSHOT_READ(clazz) \
|
| case clazz::kClassId: { \
|
| @@ -523,11 +625,11 @@ RawApiError* SnapshotReader::ReadFullSnapshot() {
|
| // Read in all the objects stored in the object store.
|
| intptr_t num_flds = (object_store->to() - object_store->from());
|
| for (intptr_t i = 0; i <= num_flds; i++) {
|
| - *(object_store->from() + i) = ReadObjectImpl();
|
| + *(object_store->from() + i) = ReadObjectImpl(kAsInlinedObject);
|
| }
|
| for (intptr_t i = 0; i < backward_references_->length(); i++) {
|
| if (!(*backward_references_)[i].is_deserialized()) {
|
| - ReadObjectImpl();
|
| + ReadObjectImpl(kAsInlinedObject);
|
| (*backward_references_)[i].set_state(kIsDeserialized);
|
| }
|
| }
|
| @@ -1011,119 +1113,6 @@ RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) {
|
| }
|
|
|
|
|
| -RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) {
|
| - // Read the class header information and lookup the class.
|
| - intptr_t class_header = Read<int32_t>();
|
| - intptr_t tags = ReadTags();
|
| - intptr_t header_id = SerializedHeaderData::decode(class_header);
|
| - if (header_id == kInstanceObjectId) {
|
| - // Object is regular dart instance.
|
| - Instance* result = reinterpret_cast<Instance*>(GetBackRef(object_id));
|
| - intptr_t instance_size = 0;
|
| - if (result == NULL) {
|
| - result = &(Instance::ZoneHandle(zone(), Instance::null()));
|
| - AddBackRef(object_id, result, kIsDeserialized);
|
| - cls_ ^= ReadObjectImpl();
|
| - ASSERT(!cls_.IsNull());
|
| - instance_size = cls_.instance_size();
|
| - ASSERT(instance_size > 0);
|
| - // Allocate the instance and read in all the fields for the object.
|
| - if (kind_ == Snapshot::kFull) {
|
| - *result ^= AllocateUninitialized(cls_.id(), instance_size);
|
| - } else {
|
| - *result ^= Object::Allocate(cls_.id(),
|
| - instance_size,
|
| - HEAP_SPACE(kind_));
|
| - }
|
| - } else {
|
| - cls_ ^= ReadObjectImpl();
|
| - ASSERT(!cls_.IsNull());
|
| - instance_size = cls_.instance_size();
|
| - }
|
| - intptr_t next_field_offset = cls_.next_field_offset();
|
| - intptr_t type_argument_field_offset = cls_.type_arguments_field_offset();
|
| - ASSERT(next_field_offset > 0);
|
| - // Instance::NextFieldOffset() returns the offset of the first field in
|
| - // a Dart object.
|
| - bool is_canonical = RawObject::IsCanonical(tags);
|
| - intptr_t offset = Instance::NextFieldOffset();
|
| - intptr_t result_cid = result->GetClassId();
|
| - while (offset < next_field_offset) {
|
| - pobj_ = is_canonical ? ReadObjectImpl() : ReadObjectRef();
|
| - result->SetFieldAtOffset(offset, pobj_);
|
| - if ((offset != type_argument_field_offset) &&
|
| - (kind_ == Snapshot::kMessage)) {
|
| - // TODO(fschneider): Consider hoisting these lookups out of the loop.
|
| - // This would involve creating a handle, since cls_ can't be reused
|
| - // across the call to ReadObjectRef.
|
| - cls_ = isolate()->class_table()->At(result_cid);
|
| - array_ = cls_.OffsetToFieldMap();
|
| - field_ ^= array_.At(offset >> kWordSizeLog2);
|
| - ASSERT(!field_.IsNull());
|
| - ASSERT(field_.Offset() == offset);
|
| - obj_ = pobj_.raw();
|
| - field_.RecordStore(obj_);
|
| - }
|
| - // TODO(fschneider): Verify the guarded cid and length for other kinds of
|
| - // snapshot (kFull, kScript) with asserts.
|
| - offset += kWordSize;
|
| - }
|
| - if (kind_ == Snapshot::kFull) {
|
| - // We create an uninitialized object in the case of full snapshots, so
|
| - // we need to initialize any remaining padding area with the Null object.
|
| - while (offset < instance_size) {
|
| - result->SetFieldAtOffset(offset, Object::null_object());
|
| - offset += kWordSize;
|
| - }
|
| - result->SetCreatedFromSnapshot();
|
| - } else if (RawObject::IsCanonical(tags)) {
|
| - *result = result->CheckAndCanonicalize(NULL);
|
| - ASSERT(!result->IsNull());
|
| - }
|
| - return result->raw();
|
| - } else if (header_id == kStaticImplicitClosureObjectId) {
|
| - // We do not use the tags as the implicit static closure
|
| - // is going to be created in this isolate or the canonical
|
| - // version already created in the isolate will be used.
|
| - return ReadStaticImplicitClosure(object_id, class_header);
|
| - }
|
| - ASSERT((class_header & kSmiTagMask) != kSmiTag);
|
| - intptr_t class_id = LookupInternalClass(class_header);
|
| - switch (class_id) {
|
| -#define SNAPSHOT_READ(clazz) \
|
| - case clazz::kClassId: { \
|
| - pobj_ = clazz::ReadFrom(this, object_id, tags, kind_); \
|
| - break; \
|
| - }
|
| - CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
|
| -#undef SNAPSHOT_READ
|
| -#define SNAPSHOT_READ(clazz) \
|
| - case kTypedData##clazz##Cid: \
|
| -
|
| - CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
|
| - tags = RawObject::ClassIdTag::update(class_id, tags);
|
| - pobj_ = TypedData::ReadFrom(this, object_id, tags, kind_);
|
| - break;
|
| - }
|
| -#undef SNAPSHOT_READ
|
| -#define SNAPSHOT_READ(clazz) \
|
| - case kExternalTypedData##clazz##Cid: \
|
| -
|
| - CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
|
| - tags = RawObject::ClassIdTag::update(class_id, tags);
|
| - pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_);
|
| - break;
|
| - }
|
| -#undef SNAPSHOT_READ
|
| - default: UNREACHABLE(); break;
|
| - }
|
| - if (kind_ == Snapshot::kFull) {
|
| - pobj_.SetCreatedFromSnapshot();
|
| - }
|
| - return pobj_.raw();
|
| -}
|
| -
|
| -
|
| void SnapshotReader::ArrayReadFrom(const Array& result,
|
| intptr_t len,
|
| intptr_t tags) {
|
| @@ -1131,13 +1120,13 @@ void SnapshotReader::ArrayReadFrom(const Array& result,
|
| result.set_tags(tags);
|
|
|
| // Setup the object fields.
|
| - *TypeArgumentsHandle() ^= ReadObjectImpl();
|
| + *TypeArgumentsHandle() ^= ReadObjectImpl(kAsInlinedObject);
|
| result.SetTypeArguments(*TypeArgumentsHandle());
|
|
|
| - bool is_canonical = RawObject::IsCanonical(tags);
|
| + bool as_reference = RawObject::IsCanonical(tags) ? false : true;
|
|
|
| for (intptr_t i = 0; i < len; i++) {
|
| - *PassiveObjectHandle() = is_canonical ? ReadObjectImpl() : ReadObjectRef();
|
| + *PassiveObjectHandle() = ReadObjectImpl(as_reference);
|
| result.SetAt(i, *PassiveObjectHandle());
|
| }
|
| }
|
| @@ -1284,7 +1273,7 @@ SnapshotWriter::SnapshotWriter(Snapshot::Kind kind,
|
|
|
|
|
| void SnapshotWriter::WriteObject(RawObject* rawobj) {
|
| - WriteObjectImpl(rawobj);
|
| + WriteObjectImpl(rawobj, kAsInlinedObject);
|
| WriteForwardedObjects();
|
| }
|
|
|
| @@ -1407,104 +1396,6 @@ void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
|
| #undef VM_OBJECT_WRITE
|
|
|
|
|
| -void SnapshotWriter::WriteObjectRef(RawObject* raw) {
|
| - // First check if object can be written as a simple predefined type.
|
| - if (CheckAndWritePredefinedObject(raw)) {
|
| - return;
|
| - }
|
| -
|
| - NoSafepointScope no_safepoint;
|
| - RawClass* cls = class_table_->At(raw->GetClassId());
|
| - intptr_t class_id = cls->ptr()->id_;
|
| - ASSERT(class_id == raw->GetClassId());
|
| - if (class_id >= kNumPredefinedCids) {
|
| - WriteInstanceRef(raw, cls);
|
| - return;
|
| - }
|
| - 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
|
| - // will serialize the object when we go through the forward list.
|
| - forward_list_->MarkAndAddObject(raw, kIsNotSerialized);
|
| -
|
| - RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
|
| -
|
| - // Write out the serialization header value for this object.
|
| - WriteInlinedObjectHeader(kOmittedObjectId);
|
| -
|
| - // Write out the class information.
|
| - WriteIndexedObject(kArrayCid);
|
| -
|
| - // Write out the length field.
|
| - Write<RawObject*>(rawarray->ptr()->length_);
|
| -
|
| - return;
|
| - }
|
| - 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
|
| - // will serialize the object when we go through the forward list.
|
| - forward_list_->MarkAndAddObject(raw, kIsNotSerialized);
|
| -
|
| - RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
|
| -
|
| - // Write out the serialization header value for this object.
|
| - WriteInlinedObjectHeader(kOmittedObjectId);
|
| -
|
| - // Write out the class information.
|
| - WriteIndexedObject(kImmutableArrayCid);
|
| -
|
| - // Write out the length field.
|
| - Write<RawObject*>(rawarray->ptr()->length_);
|
| -
|
| - return;
|
| - }
|
| - if (RawObject::IsImplicitFieldClassId(class_id)) {
|
| - WriteInstanceRef(raw, cls);
|
| - return;
|
| - }
|
| - // Add object 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 having
|
| - // been serialized so that we do not serialize the object when we go through
|
| - // the forward list.
|
| - forward_list_->MarkAndAddObject(raw, kIsSerialized);
|
| - switch (class_id) {
|
| -#define SNAPSHOT_WRITE(clazz) \
|
| - case clazz::kClassId: { \
|
| - Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \
|
| - raw_obj->WriteTo(this, kOmittedObjectId, kind_); \
|
| - return; \
|
| - } \
|
| -
|
| - CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
|
| -#undef SNAPSHOT_WRITE
|
| -#define SNAPSHOT_WRITE(clazz) \
|
| - case kTypedData##clazz##Cid: \
|
| -
|
| - CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
|
| - RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(raw);
|
| - raw_obj->WriteTo(this, kOmittedObjectId, kind_);
|
| - return;
|
| - }
|
| -#undef SNAPSHOT_WRITE
|
| -#define SNAPSHOT_WRITE(clazz) \
|
| - case kExternalTypedData##clazz##Cid: \
|
| -
|
| - CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
|
| - RawExternalTypedData* raw_obj =
|
| - reinterpret_cast<RawExternalTypedData*>(raw);
|
| - raw_obj->WriteTo(this, kOmittedObjectId, kind_);
|
| - return;
|
| - }
|
| -#undef SNAPSHOT_WRITE
|
| - default: break;
|
| - }
|
| - UNREACHABLE();
|
| -}
|
| -
|
| -
|
| // An object visitor which will iterate over all the script objects in the heap
|
| // and either count them or collect them into an array. This is used during
|
| // full snapshot generation of the VM isolate to write out all script
|
| @@ -1853,18 +1744,95 @@ bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) {
|
| }
|
|
|
|
|
| -void SnapshotWriter::WriteObjectImpl(RawObject* raw) {
|
| +void SnapshotWriter::WriteObjectImpl(RawObject* raw, bool as_reference) {
|
| // First check if object can be written as a simple predefined type.
|
| if (CheckAndWritePredefinedObject(raw)) {
|
| return;
|
| }
|
|
|
| - // Object is being serialized, add it to the forward ref list and mark
|
| - // it so that future references to this object in the snapshot will use
|
| - // an object id, instead of trying to serialize it again.
|
| + if (as_reference && !raw->IsCanonical()) {
|
| + WriteObjectRef(raw);
|
| + } else {
|
| + // Object is being serialized, add it to the forward ref list and mark
|
| + // it so that future references to this object in the snapshot will use
|
| + // an object id, instead of trying to serialize it again.
|
| + forward_list_->MarkAndAddObject(raw, kIsSerialized);
|
| +
|
| + WriteInlinedObject(raw);
|
| + }
|
| +}
|
| +
|
| +
|
| +void SnapshotWriter::WriteObjectRef(RawObject* raw) {
|
| + NoSafepointScope no_safepoint;
|
| + RawClass* cls = class_table_->At(raw->GetClassId());
|
| + intptr_t class_id = cls->ptr()->id_;
|
| + ASSERT(class_id == raw->GetClassId());
|
| + if (class_id >= kNumPredefinedCids ||
|
| + RawObject::IsImplicitFieldClassId(class_id)) {
|
| + WriteInstanceRef(raw, cls);
|
| + return;
|
| + }
|
| + if (class_id == kArrayCid || class_id == kImmutableArrayCid) {
|
| + intptr_t tags = GetObjectTags(raw);
|
| +
|
| + // 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
|
| + // will serialize the object when we go through the forward list.
|
| + forward_list_->MarkAndAddObject(raw, kIsNotSerialized);
|
| +
|
| + RawArray* rawarray = reinterpret_cast<RawArray*>(raw);
|
| +
|
| + // Write out the serialization header value for this object.
|
| + WriteInlinedObjectHeader(kOmittedObjectId);
|
| +
|
| + // Write out the class information.
|
| + WriteIndexedObject(class_id);
|
| + WriteTags(tags);
|
| +
|
| + // Write out the length field.
|
| + Write<RawObject*>(rawarray->ptr()->length_);
|
| +
|
| + return;
|
| + }
|
| + // Add object 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 having
|
| + // been serialized so that we do not serialize the object when we go through
|
| + // the forward list.
|
| forward_list_->MarkAndAddObject(raw, kIsSerialized);
|
| + switch (class_id) {
|
| +#define SNAPSHOT_WRITE(clazz) \
|
| + case clazz::kClassId: { \
|
| + Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw); \
|
| + raw_obj->WriteTo(this, kOmittedObjectId, kind_); \
|
| + return; \
|
| + } \
|
|
|
| - WriteInlinedObject(raw);
|
| + CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
|
| +#undef SNAPSHOT_WRITE
|
| +#define SNAPSHOT_WRITE(clazz) \
|
| + case kTypedData##clazz##Cid: \
|
| +
|
| + CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
|
| + RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(raw);
|
| + raw_obj->WriteTo(this, kOmittedObjectId, kind_);
|
| + return;
|
| + }
|
| +#undef SNAPSHOT_WRITE
|
| +#define SNAPSHOT_WRITE(clazz) \
|
| + case kExternalTypedData##clazz##Cid: \
|
| +
|
| + CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
|
| + RawExternalTypedData* raw_obj =
|
| + reinterpret_cast<RawExternalTypedData*>(raw);
|
| + raw_obj->WriteTo(this, kOmittedObjectId, kind_);
|
| + return;
|
| + }
|
| +#undef SNAPSHOT_WRITE
|
| + default: break;
|
| + }
|
| + UNREACHABLE();
|
| }
|
|
|
|
|
| @@ -1994,8 +1962,8 @@ void SnapshotWriter::WriteClassId(RawClass* cls) {
|
| // Write out the library url and class name.
|
| RawLibrary* library = cls->ptr()->library_;
|
| ASSERT(library != Library::null());
|
| - WriteObjectImpl(library->ptr()->url_);
|
| - WriteObjectImpl(cls->ptr()->name_);
|
| + WriteObjectImpl(library->ptr()->url_, kAsInlinedObject);
|
| + WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject);
|
| }
|
|
|
|
|
| @@ -2016,9 +1984,9 @@ void SnapshotWriter::WriteStaticImplicitClosure(intptr_t object_id,
|
| ASSERT(cls != Class::null());
|
| RawLibrary* library = cls->ptr()->library_;
|
| ASSERT(library != Library::null());
|
| - WriteObjectImpl(library->ptr()->url_);
|
| - WriteObjectImpl(cls->ptr()->name_);
|
| - WriteObjectImpl(func->ptr()->name_);
|
| + WriteObjectImpl(library->ptr()->url_, kAsInlinedObject);
|
| + WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject);
|
| + WriteObjectImpl(func->ptr()->name_, kAsInlinedObject);
|
| }
|
|
|
|
|
| @@ -2041,16 +2009,12 @@ void SnapshotWriter::ArrayWriteTo(intptr_t object_id,
|
| Write<RawObject*>(length);
|
|
|
| // Write out the type arguments.
|
| - WriteObjectImpl(type_arguments);
|
| + WriteObjectImpl(type_arguments, kAsInlinedObject);
|
|
|
| // Write out the individual object ids.
|
| - bool is_canonical = RawObject::IsCanonical(tags);
|
| + bool as_reference = RawObject::IsCanonical(tags) ? false : true;
|
| for (intptr_t i = 0; i < len; i++) {
|
| - if (is_canonical) {
|
| - WriteObjectImpl(data[i]);
|
| - } else {
|
| - WriteObjectRef(data[i]);
|
| - }
|
| + WriteObjectImpl(data[i], as_reference);
|
| }
|
| }
|
|
|
| @@ -2159,21 +2123,17 @@ void SnapshotWriter::WriteInstance(intptr_t object_id,
|
| WriteTags(tags);
|
|
|
| // Write out the class information for this object.
|
| - WriteObjectImpl(cls);
|
| + WriteObjectImpl(cls, kAsInlinedObject);
|
|
|
| // Write out all the fields for the object.
|
| // Instance::NextFieldOffset() returns the offset of the first field in
|
| // a Dart object.
|
| - bool is_canonical = RawObject::IsCanonical(tags);
|
| + bool as_reference = RawObject::IsCanonical(tags) ? false : true;
|
| intptr_t offset = Instance::NextFieldOffset();
|
| while (offset < next_field_offset) {
|
| RawObject* raw_obj = *reinterpret_cast<RawObject**>(
|
| reinterpret_cast<uword>(raw->ptr()) + offset);
|
| - if (is_canonical) {
|
| - WriteObjectImpl(raw_obj);
|
| - } else {
|
| - WriteObjectRef(raw_obj);
|
| - }
|
| + WriteObjectImpl(raw_obj, as_reference);
|
| offset += kWordSize;
|
| }
|
| return;
|
| @@ -2205,6 +2165,7 @@ void SnapshotWriter::WriteInstanceRef(RawObject* raw, RawClass* cls) {
|
| // 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
|
| // will serialize the object when we go through the forward list.
|
| + intptr_t tags = raw->ptr()->tags_;
|
| forward_list_->MarkAndAddObject(raw, kIsNotSerialized);
|
|
|
| // Write out the serialization header value for this object.
|
| @@ -2212,9 +2173,10 @@ void SnapshotWriter::WriteInstanceRef(RawObject* raw, RawClass* cls) {
|
|
|
| // Indicate this is an instance object.
|
| Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId));
|
| + WriteTags(tags);
|
|
|
| // Write out the class information for this object.
|
| - WriteObjectImpl(cls);
|
| + WriteObjectImpl(cls, kAsInlinedObject);
|
| }
|
|
|
|
|
| @@ -2313,11 +2275,7 @@ void ScriptSnapshotWriter::WriteScriptSnapshot(const Library& lib) {
|
| void SnapshotWriterVisitor::VisitPointers(RawObject** first, RawObject** last) {
|
| for (RawObject** current = first; current <= last; current++) {
|
| RawObject* raw_obj = *current;
|
| - if (as_references_) {
|
| - writer_->WriteObjectRef(raw_obj);
|
| - } else {
|
| - writer_->WriteObjectImpl(raw_obj);
|
| - }
|
| + writer_->WriteObjectImpl(raw_obj, as_references_);
|
| }
|
| }
|
|
|
|
|