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_); |
} |
} |