Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(423)

Unified Diff: runtime/vm/snapshot.cc

Issue 1255003004: Implement patch records to patch canonical objects. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: merged-to-tot Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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());
}
}

Powered by Google App Engine
This is Rietveld 408576698