Chromium Code Reviews| Index: runtime/vm/snapshot.cc |
| diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc |
| index 391c9fc14e10c746c886084654300493d496eba4..c18978736b33c5b4956518ceb7099267129ec50e 100644 |
| --- a/runtime/vm/snapshot.cc |
| +++ b/runtime/vm/snapshot.cc |
| @@ -213,6 +213,7 @@ RawObject* SnapshotReader::ReadObject() { |
| (*backward_references_)[i].set_state(kIsDeserialized); |
| } |
| } |
| + ProcessDeferredCanonicalizations(); |
| return obj.raw(); |
| } else { |
| // An error occurred while reading, return the error object. |
| @@ -235,7 +236,7 @@ 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, kInvalidPatchIndex, 0); |
| library_ = Library::LookupLibrary(str_); |
| if (library_.IsNull() || !library_.Loaded()) { |
| SetReadException("Invalid object found in message."); |
| @@ -292,13 +293,16 @@ RawObject* SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id, |
| } |
| -RawObject* SnapshotReader::ReadObjectImpl() { |
| +RawObject* SnapshotReader::ReadObjectImpl(intptr_t patch_object_id, |
| + intptr_t patch_offset) { |
| 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)); |
| + return ReadObjectImpl(static_cast<intptr_t>(value), |
| + patch_object_id, |
| + patch_offset); |
| } |
| @@ -331,24 +335,29 @@ RawObject* SnapshotReader::VmIsolateSnapshotObject(intptr_t index) const { |
| } |
| -RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value) { |
| +RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value, |
| + intptr_t patch_object_id, |
| + intptr_t patch_offset) { |
| if (IsVMIsolateObject(header_value)) { |
| return ReadVMIsolateObject(header_value); |
| } else { |
| if (SerializedHeaderTag::decode(header_value) == kObjectId) { |
| - return ReadIndexedObject(SerializedHeaderData::decode(header_value)); |
| + return ReadIndexedObject(SerializedHeaderData::decode(header_value), |
| + patch_object_id, |
| + patch_offset); |
| } |
| ASSERT(SerializedHeaderTag::decode(header_value) == kInlined); |
| intptr_t object_id = SerializedHeaderData::decode(header_value); |
| if (object_id == kOmittedObjectId) { |
| object_id = NextAvailableObjectId(); |
| } |
| - return ReadInlinedObject(object_id); |
| + return ReadInlinedObject(object_id, patch_object_id, patch_offset); |
| } |
| } |
| -RawObject* SnapshotReader::ReadObjectRef() { |
| +RawObject* SnapshotReader::ReadObjectRef(intptr_t patch_object_id, |
| + intptr_t patch_offset) { |
| int64_t header_value = Read<int64_t>(); |
| if ((header_value & kSmiTagMask) == kSmiTag) { |
| return NewInteger(header_value); |
| @@ -358,7 +367,9 @@ RawObject* SnapshotReader::ReadObjectRef() { |
| if (IsVMIsolateObject(value)) { |
| return ReadVMIsolateObject(value); |
| } else if (SerializedHeaderTag::decode(value) == kObjectId) { |
| - return ReadIndexedObject(SerializedHeaderData::decode(value)); |
| + return ReadIndexedObject(SerializedHeaderData::decode(value), |
| + patch_object_id, |
| + patch_offset); |
| } |
| ASSERT(SerializedHeaderTag::decode(value) == kInlined); |
| intptr_t object_id = SerializedHeaderData::decode(value); |
| @@ -456,18 +467,20 @@ RawObject* SnapshotReader::ReadObjectRef() { |
| if (kind_ == Snapshot::kFull) { |
| pobj_.SetCreatedFromSnapshot(); |
| } |
| + AddPatchRecord(object_id, patch_object_id, patch_offset); |
| return pobj_.raw(); |
| } |
| void SnapshotReader::AddBackRef(intptr_t id, |
| Object* obj, |
| - DeserializeState state) { |
| + DeserializeState state, |
| + bool defer_canonicalization) { |
| intptr_t index = (id - kMaxPredefinedObjectIds); |
| ASSERT(index >= max_vm_isolate_object_id_); |
| index -= max_vm_isolate_object_id_; |
| ASSERT(index == backward_references_->length()); |
| - BackRefNode node(obj, state); |
| + BackRefNode node(obj, state, defer_canonicalization); |
| backward_references_->Add(node); |
| } |
| @@ -992,7 +1005,9 @@ RawObject* SnapshotReader::ReadVMIsolateObject(intptr_t header_value) { |
| } |
| -RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) { |
| +RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id, |
| + intptr_t patch_object_id, |
| + intptr_t patch_offset) { |
| intptr_t class_id = ClassIdFromObjectId(object_id); |
| if (IsObjectStoreClassId(class_id)) { |
| return isolate()->class_table()->At(class_id); // get singleton class. |
| @@ -1007,15 +1022,19 @@ RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id) { |
| if (index < max_vm_isolate_object_id_) { |
| return VmIsolateSnapshotObject(index); |
| } |
| + AddPatchRecord(object_id, patch_object_id, patch_offset); |
| return GetBackRef(object_id)->raw(); |
| } |
| -RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) { |
| +RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id, |
| + intptr_t patch_object_id, |
| + intptr_t patch_offset) { |
| // 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); |
| + bool is_canonical = RawObject::IsCanonical(tags); |
| if (header_id == kInstanceObjectId) { |
| // Object is regular dart instance. |
| Instance* result = reinterpret_cast<Instance*>(GetBackRef(object_id)); |
| @@ -1045,7 +1064,6 @@ RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) { |
| 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) { |
| @@ -1076,7 +1094,7 @@ RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) { |
| offset += kWordSize; |
| } |
| result->SetCreatedFromSnapshot(); |
| - } else if (RawObject::IsCanonical(tags)) { |
| + } else if (is_canonical) { |
| *result = result->CheckAndCanonicalize(NULL); |
| ASSERT(!result->IsNull()); |
| } |
| @@ -1120,24 +1138,90 @@ RawObject* SnapshotReader::ReadInlinedObject(intptr_t object_id) { |
| if (kind_ == Snapshot::kFull) { |
| pobj_.SetCreatedFromSnapshot(); |
| } |
| + AddPatchRecord(object_id, patch_object_id, patch_offset); |
| return pobj_.raw(); |
| } |
| -void SnapshotReader::ArrayReadFrom(const Array& result, |
| +void SnapshotReader::AddPatchRecord(intptr_t object_id, |
| + intptr_t patch_object_id, |
| + intptr_t patch_offset) { |
| + if (patch_object_id != kInvalidPatchIndex && kind() != Snapshot::kFull) { |
| + ASSERT(object_id >= kMaxPredefinedObjectIds); |
| + intptr_t index = (object_id - kMaxPredefinedObjectIds); |
| + ASSERT(index >= max_vm_isolate_object_id_); |
| + index -= max_vm_isolate_object_id_; |
| + ASSERT(index < backward_references_->length()); |
| + BackRefNode& ref = (*backward_references_)[index]; |
| + if (ref.defer_canonicalization()) { |
|
rmacnak
2015/07/28 22:43:22
Redundant with check in AddPatchRecord.
siva
2015/07/30 02:03:48
Removed check.
|
| + ref.AddPatchRecord(patch_object_id, patch_offset); |
| + } |
| + } |
| +} |
| + |
| + |
| +void SnapshotReader::ProcessDeferredCanonicalizations() { |
| + AbstractType& typeobj = AbstractType::Handle(); |
| + TypeArguments& typeargs = TypeArguments::Handle(); |
| + Object& newobj = Object::Handle(); |
| + for (intptr_t i = 0; i < backward_references_->length(); i++) { |
| + BackRefNode& backref = (*backward_references_)[i]; |
| + if (backref.defer_canonicalization()) { |
| + Object* objref = backref.reference(); |
| + // Object should either be an abstract type or a type argument. |
| + if (objref->IsAbstractType()) { |
| + typeobj ^= objref->raw(); |
| + typeobj.ClearCanonical(); |
| + newobj = typeobj.Canonicalize(); |
| + } else { |
| + ASSERT(objref->IsTypeArguments()); |
| + typeargs ^= objref->raw(); |
| + typeargs.ClearCanonical(); |
| + newobj = typeargs.Canonicalize(); |
| + } |
| + if (newobj.raw() == objref->raw()) { |
| + // Restore Canonical bit. |
| + objref->SetCanonical(); |
| + } else { |
| + ZoneGrowableArray<intptr_t>* patches = backref.patch_records(); |
| + ASSERT(newobj.IsCanonical()); |
| + ASSERT(patches != NULL); |
| + for (intptr_t j = 0; j < patches->length(); j+=2) { |
| + NoSafepointScope no_safepoint; |
| + intptr_t patch_object_id = (*patches)[j]; |
| + intptr_t patch_offset = (*patches)[j + 1]; |
| + Object* target = GetBackRef(patch_object_id); |
| + RawObject** rawptr = |
| + reinterpret_cast<RawObject**>(target->raw()->ptr()); |
| + target->StorePointer((rawptr + patch_offset), newobj.raw()); |
| + } |
| + } |
| + } |
| + } |
| +} |
| + |
| + |
| +void SnapshotReader::ArrayReadFrom(intptr_t object_id, |
| + const Array& result, |
| intptr_t len, |
| intptr_t tags) { |
| // Set the object tags. |
| result.set_tags(tags); |
| // Setup the object fields. |
| - *TypeArgumentsHandle() ^= ReadObjectImpl(); |
| + intptr_t typeargs_offset = |
| + reinterpret_cast<RawObject**>(&result.raw()->ptr()->type_arguments_) - |
| + reinterpret_cast<RawObject**>(result.raw()->ptr()); |
| + *TypeArgumentsHandle() ^= ReadObjectImpl(object_id, typeargs_offset); |
| result.SetTypeArguments(*TypeArgumentsHandle()); |
| bool is_canonical = RawObject::IsCanonical(tags); |
| + intptr_t offset = result.raw_ptr()->data() - |
| + reinterpret_cast<RawObject**>(result.raw()->ptr()); |
| for (intptr_t i = 0; i < len; i++) { |
| - *PassiveObjectHandle() = is_canonical ? ReadObjectImpl() : ReadObjectRef(); |
| + *PassiveObjectHandle() = is_canonical ? |
| + ReadObjectImpl(object_id, i) : ReadObjectRef(object_id, (i + offset)); |
| result.SetAt(i, *PassiveObjectHandle()); |
| } |
| } |