Index: runtime/vm/clustered_snapshot.cc |
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc |
index 8b6eb0a975b9cf237d9ce6f9daaa8db36c3e8dd1..11d9dd050935b76e8347b12e12a45f2de8e12989 100644 |
--- a/runtime/vm/clustered_snapshot.cc |
+++ b/runtime/vm/clustered_snapshot.cc |
@@ -114,8 +114,7 @@ class ClassSerializationCluster : public SerializationCluster { |
} |
intptr_t class_id = cls->ptr()->id_; |
if (class_id == kIllegalCid) { |
- FATAL1("Attempting to serialize class with illegal cid: %s\n", |
- Class::Handle(cls).ToCString()); |
+ s->UnexpectedObject(cls, "Class with illegal cid"); |
} |
s->WriteCid(class_id); |
s->Write<int32_t>(cls->ptr()->instance_size_in_words_); |
@@ -4504,7 +4503,13 @@ Serializer::Serializer(Thread* thread, |
num_cids_(0), |
num_base_objects_(0), |
num_written_objects_(0), |
- next_ref_index_(1) { |
+ next_ref_index_(1) |
+#if defined(SNAPSHOT_BACKTRACE) |
+ , |
+ current_parent_(Object::null()), |
+ parent_pairs_() |
+#endif |
+{ |
num_cids_ = thread->isolate()->class_table()->NumCids(); |
clusters_by_cid_ = new SerializationCluster*[num_cids_]; |
for (intptr_t i = 0; i < num_cids_; i++) { |
@@ -4649,6 +4654,45 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) { |
} |
+void Serializer::Push(RawObject* object) { |
+ if (!object->IsHeapObject()) { |
+ RawSmi* smi = Smi::RawCast(object); |
+ if (smi_ids_.Lookup(smi) == NULL) { |
+ SmiObjectIdPair pair; |
+ pair.smi_ = smi; |
+ pair.id_ = 1; |
+ smi_ids_.Insert(pair); |
+ stack_.Add(object); |
+ num_written_objects_++; |
+ } |
+ return; |
+ } |
+ |
+ if (object->IsCode() && !Snapshot::IncludesCode(kind_)) { |
+ return; // Do not trace, will write null. |
+ } |
+ |
+ if (object->IsSendPort()) { |
+ // TODO(rmacnak): Do a better job of resetting fields in precompilation |
+ // and assert this is unreachable. |
+ return; // Do not trace, will write null. |
+ } |
+ |
+ intptr_t id = heap_->GetObjectId(object); |
+ if (id == 0) { |
+ heap_->SetObjectId(object, 1); |
+ ASSERT(heap_->GetObjectId(object) != 0); |
+ stack_.Add(object); |
+ num_written_objects_++; |
+ |
+#if defined(SNAPSHOT_BACKTRACE) |
+ parent_pairs_.Add(&Object::Handle(object)); |
+ parent_pairs_.Add(&Object::Handle(current_parent_)); |
+#endif |
+ } |
+} |
+ |
+ |
void Serializer::Trace(RawObject* object) { |
intptr_t cid; |
if (!object->IsHeapObject()) { |
@@ -4665,8 +4709,42 @@ void Serializer::Trace(RawObject* object) { |
clusters_by_cid_[cid] = cluster; |
} |
ASSERT(cluster != NULL); |
+ |
+#if defined(SNAPSHOT_BACKTRACE) |
+ current_parent_ = object; |
+#endif |
+ |
cluster->Trace(this, object); |
+ |
+#if defined(SNAPSHOT_BACKTRACE) |
+ current_parent_ = Object::null(); |
+#endif |
+} |
+ |
+ |
+void Serializer::UnexpectedObject(RawObject* raw_object, const char* message) { |
+ Object& object = Object::Handle(raw_object); |
+ OS::PrintErr("Unexpected object (%s): %s\n", message, object.ToCString()); |
+#if defined(SNAPSHOT_BACKTRACE) |
+ while (!object.IsNull()) { |
+ object = ParentOf(object); |
+ OS::PrintErr("referenced by %s\n", object.ToCString()); |
+ } |
+#endif |
+ OS::Abort(); |
+} |
+ |
+ |
+#if defined(SNAPSHOT_BACKTRACE) |
+RawObject* Serializer::ParentOf(const Object& object) { |
+ for (intptr_t i = 0; i < parent_pairs_.length(); i += 2) { |
+ if (parent_pairs_[i]->raw() == object.raw()) { |
+ return parent_pairs_[i + 1]->raw(); |
+ } |
+ } |
+ return Object::null(); |
} |
+#endif // SNAPSHOT_BACKTRACE |
void Serializer::WriteVersionAndFeatures() { |