Chromium Code Reviews| Index: runtime/vm/object_graph.cc |
| diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc |
| index c80c80c4f3e33e9b9c2c02b8b078a0718e42c728..91a5d601d3592b675ce5a529a21948fac56d357c 100644 |
| --- a/runtime/vm/object_graph.cc |
| +++ b/runtime/vm/object_graph.cc |
| @@ -8,6 +8,7 @@ |
| #include "vm/growable_array.h" |
| #include "vm/isolate.h" |
| #include "vm/object.h" |
| +#include "vm/object_store.h" |
| #include "vm/raw_object.h" |
| #include "vm/reusable_handles.h" |
| #include "vm/visitor.h" |
| @@ -487,8 +488,13 @@ static void WritePtr(RawObject* raw, WriteStream* stream) { |
| class WritePointerVisitor : public ObjectPointerVisitor { |
| public: |
| - WritePointerVisitor(Isolate* isolate, WriteStream* stream) |
| - : ObjectPointerVisitor(isolate), stream_(stream), count_(0) {} |
| + WritePointerVisitor(Isolate* isolate, |
| + WriteStream* stream, |
| + bool only_instances) |
| + : ObjectPointerVisitor(isolate), |
| + stream_(stream), |
| + only_instances_(only_instances), |
| + count_(0) {} |
| virtual void VisitPointers(RawObject** first, RawObject** last) { |
| for (RawObject** current = first; current <= last; ++current) { |
| RawObject* object = *current; |
| @@ -498,6 +504,9 @@ class WritePointerVisitor : public ObjectPointerVisitor { |
| // we'll need to encode which fields were omitted here. |
| continue; |
| } |
| + if (only_instances_ && (object->GetClassId() < kInstanceCid)) { |
| + continue; |
| + } |
| WritePtr(object, stream_); |
| ++count_; |
| } |
| @@ -507,6 +516,7 @@ class WritePointerVisitor : public ObjectPointerVisitor { |
| private: |
| WriteStream* stream_; |
| + bool only_instances_; |
| intptr_t count_; |
| }; |
| @@ -524,8 +534,13 @@ static void WriteHeader(RawObject* raw, |
| class WriteGraphVisitor : public ObjectGraph::Visitor { |
| public: |
| - WriteGraphVisitor(Isolate* isolate, WriteStream* stream) |
| - : stream_(stream), ptr_writer_(isolate, stream), count_(0) {} |
| + WriteGraphVisitor(Isolate* isolate, |
| + WriteStream* stream, |
| + ObjectGraph::SnapshotRoots roots) |
| + : stream_(stream), |
| + ptr_writer_(isolate, stream, roots == ObjectGraph::kUser), |
| + roots_(roots), |
| + count_(0) {} |
| virtual Direction VisitObject(ObjectGraph::StackIterator* it) { |
| RawObject* raw_obj = it->Get(); |
| @@ -533,11 +548,13 @@ class WriteGraphVisitor : public ObjectGraph::Visitor { |
| REUSABLE_OBJECT_HANDLESCOPE(thread); |
| Object& obj = thread->ObjectHandle(); |
| obj = raw_obj; |
| - // Each object is a header + a zero-terminated list of its neighbors. |
| - WriteHeader(raw_obj, raw_obj->Size(), obj.GetClassId(), stream_); |
| - raw_obj->VisitPointers(&ptr_writer_); |
| - stream_->WriteUnsigned(0); |
| - ++count_; |
| + if ((roots_ == ObjectGraph::kVM) || obj.IsField() || obj.IsInstance()) { |
| + // Each object is a header + a zero-terminated list of its neighbors. |
| + WriteHeader(raw_obj, raw_obj->Size(), obj.GetClassId(), stream_); |
| + raw_obj->VisitPointers(&ptr_writer_); |
| + stream_->WriteUnsigned(0); |
| + ++count_; |
| + } |
| return kProceed; |
| } |
| @@ -546,29 +563,99 @@ class WriteGraphVisitor : public ObjectGraph::Visitor { |
| private: |
| WriteStream* stream_; |
| WritePointerVisitor ptr_writer_; |
| + ObjectGraph::SnapshotRoots roots_; |
| intptr_t count_; |
| }; |
| -intptr_t ObjectGraph::Serialize(WriteStream* stream, bool collect_garbage) { |
| +static void IterateUserFields(ObjectPointerVisitor* visitor) { |
| + Thread* thread = Thread::Current(); |
| + // Scope to prevent handles create here from appearing as stack references. |
| + HANDLESCOPE(thread); |
| + Zone* zone = thread->zone(); |
| + const GrowableObjectArray& libraries = GrowableObjectArray::Handle( |
| + zone, thread->isolate()->object_store()->libraries()); |
| + Library& library = Library::Handle(zone); |
| + Object& entry = Object::Handle(zone); |
| + Class& cls = Class::Handle(zone); |
| + Array& fields = Array::Handle(zone); |
| + Field& field = Field::Handle(zone); |
| + for (intptr_t i = 0; i < libraries.Length(); i++) { |
| + library ^= libraries.At(i); |
| + DictionaryIterator entries(library); |
| + while (entries.HasNext()) { |
| + entry = entries.GetNext(); |
| + if (entry.IsClass()) { |
| + cls ^= entry.raw(); |
| + fields = cls.fields(); |
| + for (intptr_t j = 0; j < fields.Length(); j++) { |
| + field ^= fields.At(j); |
| + RawObject* ptr = field.raw(); |
| + visitor->VisitPointer(&ptr); |
| + } |
| + } else if (entry.IsField()) { |
| + field ^= entry.raw(); |
| + RawObject* ptr = field.raw(); |
| + visitor->VisitPointer(&ptr); |
| + } |
| + } |
| + } |
| +} |
| + |
| + |
| +intptr_t ObjectGraph::Serialize(WriteStream* stream, |
| + SnapshotRoots roots, |
| + bool collect_garbage) { |
| if (collect_garbage) { |
| isolate()->heap()->CollectAllGarbage(); |
| } |
| // Current encoding assumes objects do not move, so promote everything to old. |
| isolate()->heap()->new_space()->Evacuate(); |
| - WriteGraphVisitor visitor(isolate(), stream); |
| + RawObject* kRootAddress = reinterpret_cast<RawObject*>(kHeapObjectTag); |
| + const intptr_t kRootCid = 0; |
|
Cutch
2016/11/18 20:40:31
maybe move this and kStackCid into the real class
rmacnak
2016/11/18 22:34:02
Done.
|
| + RawObject* kStackAddress = |
| + reinterpret_cast<RawObject*>(kObjectAlignment + kHeapObjectTag); |
| + // Keep in sync with runtime/observatory/lib/object_graph.dart. |
| + const intptr_t kStackCid = 1; |
| + |
| stream->WriteUnsigned(kObjectAlignment); |
| - stream->WriteUnsigned(0); |
| - stream->WriteUnsigned(0); |
| - stream->WriteUnsigned(0); |
| - { |
| - WritePointerVisitor ptr_writer(isolate(), stream); |
| + |
| + if (roots == kVM) { |
| + // Write root "object". |
| + WriteHeader(kRootAddress, 0, kRootCid, stream); |
| + WritePointerVisitor ptr_writer(isolate(), stream, false); |
| isolate()->IterateObjectPointers(&ptr_writer, false); |
| + stream->WriteUnsigned(0); |
| + } else { |
| + { |
| + // Write root "object". |
| + WriteHeader(kRootAddress, 0, kRootCid, stream); |
| + WritePointerVisitor ptr_writer(isolate(), stream, false); |
| + IterateUserFields(&ptr_writer); |
| + WritePtr(kStackAddress, stream); |
| + stream->WriteUnsigned(0); |
| + } |
| + |
| + { |
| + // Write stack "object". |
| + WriteHeader(kStackAddress, 0, kStackCid, stream); |
| + WritePointerVisitor ptr_writer(isolate(), stream, true); |
| + isolate()->IterateStackPointers(&ptr_writer, false); |
| + stream->WriteUnsigned(0); |
| + } |
| } |
| - stream->WriteUnsigned(0); |
| + |
| + WriteGraphVisitor visitor(isolate(), stream, roots); |
| IterateObjects(&visitor); |
| - return visitor.count() + 1; // + root |
| + |
| + intptr_t object_count = visitor.count(); |
| + if (roots == kVM) { |
| + object_count += 1; // root |
| + } else { |
| + object_count += 2; // root and stack |
| + } |
| + return object_count; |
| } |
| } // namespace dart |