| Index: runtime/vm/object_graph.cc
|
| diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
|
| index 1c3373f4200ed3876fd1286003438cfd02c58e1e..0f630c7ff04d6393513ece058414fd1f461f0ba7 100644
|
| --- a/runtime/vm/object_graph.cc
|
| +++ b/runtime/vm/object_graph.cc
|
| @@ -26,12 +26,21 @@ namespace dart {
|
| class ObjectGraph::Stack : public ObjectPointerVisitor {
|
| public:
|
| explicit Stack(Isolate* isolate)
|
| - : ObjectPointerVisitor(isolate), data_(kInitialCapacity) {}
|
| + : ObjectPointerVisitor(isolate),
|
| + include_vm_objects_(true),
|
| + data_(kInitialCapacity) {}
|
|
|
| // Marks and pushes. Used to initialize this stack with roots.
|
| virtual void VisitPointers(RawObject** first, RawObject** last) {
|
| for (RawObject** current = first; current <= last; ++current) {
|
| if ((*current)->IsHeapObject() && !(*current)->IsMarked()) {
|
| + if (!include_vm_objects_) {
|
| + intptr_t cid = (*current)->GetClassId();
|
| + if ((cid < kInstanceCid) && (cid != kContextCid) &&
|
| + (cid != kFieldCid)) {
|
| + continue;
|
| + }
|
| + }
|
| (*current)->SetMarkBit();
|
| Node node;
|
| node.ptr = current;
|
| @@ -69,6 +78,8 @@ class ObjectGraph::Stack : public ObjectPointerVisitor {
|
| }
|
| }
|
|
|
| + bool include_vm_objects_;
|
| +
|
| private:
|
| struct Node {
|
| RawObject** ptr; // kSentinel for the sentinel node.
|
| @@ -151,6 +162,40 @@ class Unmarker : public ObjectVisitor {
|
| DISALLOW_COPY_AND_ASSIGN(Unmarker);
|
| };
|
|
|
| +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);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| ObjectGraph::ObjectGraph(Thread* thread) : StackResource(thread) {
|
| // The VM isolate has all its objects pre-marked, so iterating over it
|
| // would be a no-op.
|
| @@ -167,6 +212,15 @@ void ObjectGraph::IterateObjects(ObjectGraph::Visitor* visitor) {
|
| Unmarker::UnmarkAll(isolate());
|
| }
|
|
|
| +void ObjectGraph::IterateUserObjects(ObjectGraph::Visitor* visitor) {
|
| + NoSafepointScope no_safepoint_scope_;
|
| + Stack stack(isolate());
|
| + IterateUserFields(&stack);
|
| + stack.include_vm_objects_ = false;
|
| + stack.TraverseGraph(visitor);
|
| + Unmarker::UnmarkAll(isolate());
|
| +}
|
| +
|
| void ObjectGraph::IterateObjectsFrom(const Object& root,
|
| ObjectGraph::Visitor* visitor) {
|
| NoSafepointScope no_safepoint_scope_;
|
| @@ -377,7 +431,10 @@ intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) {
|
| RawObject* raw = obj->raw();
|
| *obj = Object::null();
|
| RetainingPathVisitor visitor(raw, path);
|
| - IterateObjects(&visitor);
|
| + IterateUserObjects(&visitor);
|
| + if (visitor.length() == 0) {
|
| + IterateObjects(&visitor);
|
| + }
|
| *obj = raw;
|
| return visitor.length();
|
| }
|
| @@ -544,40 +601,6 @@ class WriteGraphVisitor : public ObjectGraph::Visitor {
|
| intptr_t count_;
|
| };
|
|
|
| -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) {
|
|
|