Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/object_graph.h" | 5 #include "vm/object_graph.h" |
| 6 | 6 |
| 7 #include "vm/dart.h" | 7 #include "vm/dart.h" |
| 8 #include "vm/growable_array.h" | 8 #include "vm/growable_array.h" |
| 9 #include "vm/isolate.h" | 9 #include "vm/isolate.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| 11 #include "vm/object_store.h" | 11 #include "vm/object_store.h" |
| 12 #include "vm/raw_object.h" | 12 #include "vm/raw_object.h" |
| 13 #include "vm/reusable_handles.h" | 13 #include "vm/reusable_handles.h" |
| 14 #include "vm/visitor.h" | 14 #include "vm/visitor.h" |
| 15 | 15 |
| 16 namespace dart { | 16 namespace dart { |
| 17 | 17 |
| 18 // The state of a pre-order, depth-first traversal of an object graph. | 18 // The state of a pre-order, depth-first traversal of an object graph. |
| 19 // When a node is visited, *all* its children are pushed to the stack at once. | 19 // When a node is visited, *all* its children are pushed to the stack at once. |
| 20 // We insert a sentinel between the node and its children on the stack, to | 20 // We insert a sentinel between the node and its children on the stack, to |
| 21 // remember that the node has been visited. The node is kept on the stack while | 21 // remember that the node has been visited. The node is kept on the stack while |
| 22 // its children are processed, to give the visitor a complete chain of parents. | 22 // its children are processed, to give the visitor a complete chain of parents. |
| 23 // | 23 // |
| 24 // TODO(koda): Potential optimizations: | 24 // TODO(koda): Potential optimizations: |
| 25 // - Use tag bits for compact Node and sentinel representations. | 25 // - Use tag bits for compact Node and sentinel representations. |
| 26 class ObjectGraph::Stack : public ObjectPointerVisitor { | 26 class ObjectGraph::Stack : public ObjectPointerVisitor { |
| 27 public: | 27 public: |
| 28 explicit Stack(Isolate* isolate) | 28 explicit Stack(Isolate* isolate) |
| 29 : ObjectPointerVisitor(isolate), data_(kInitialCapacity) {} | 29 : ObjectPointerVisitor(isolate), |
| 30 include_vm_obj(true), | |
| 31 data_(kInitialCapacity) {} | |
| 30 | 32 |
| 31 // Marks and pushes. Used to initialize this stack with roots. | 33 // Marks and pushes. Used to initialize this stack with roots. |
| 32 virtual void VisitPointers(RawObject** first, RawObject** last) { | 34 virtual void VisitPointers(RawObject** first, RawObject** last) { |
| 33 for (RawObject** current = first; current <= last; ++current) { | 35 for (RawObject** current = first; current <= last; ++current) { |
| 34 if ((*current)->IsHeapObject() && !(*current)->IsMarked()) { | 36 if ((*current)->IsHeapObject() && !(*current)->IsMarked()) { |
| 37 if (!include_vm_obj) { | |
|
cbernaschina
2017/07/25 21:09:22
Can we make this more generic?
Maybe storing a fu
danunez
2017/07/25 22:24:54
I like this idea and we discussed this a bit offli
| |
| 38 Object& o = Object::Handle(*current); | |
|
rmacnak
2017/07/25 21:55:21
Allocating a handle here is too expensive.
*curre
danunez
2017/07/25 22:24:54
RawObject::GetClassId() is private. I can make it
rmacnak
2017/07/26 00:25:40
Make ObjectGraph::Stack a friend instead. I'm sort
| |
| 39 intptr_t cid = o.GetClassId(); | |
| 40 if (cid < kInstanceCid && cid != kContextCid) { | |
| 41 continue; | |
| 42 } | |
| 43 } | |
| 35 (*current)->SetMarkBit(); | 44 (*current)->SetMarkBit(); |
| 36 Node node; | 45 Node node; |
| 37 node.ptr = current; | 46 node.ptr = current; |
| 38 node.obj = *current; | 47 node.obj = *current; |
| 39 data_.Add(node); | 48 data_.Add(node); |
| 40 } | 49 } |
| 41 } | 50 } |
| 42 } | 51 } |
| 43 | 52 |
| 44 // Traverses the object graph from the current state. | 53 // Traverses the object graph from the current state. |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 62 obj->VisitPointers(this); | 71 obj->VisitPointers(this); |
| 63 break; | 72 break; |
| 64 case ObjectGraph::Visitor::kBacktrack: | 73 case ObjectGraph::Visitor::kBacktrack: |
| 65 break; | 74 break; |
| 66 case ObjectGraph::Visitor::kAbort: | 75 case ObjectGraph::Visitor::kAbort: |
| 67 return; | 76 return; |
| 68 } | 77 } |
| 69 } | 78 } |
| 70 } | 79 } |
| 71 | 80 |
| 81 bool include_vm_obj; | |
|
rmacnak
2017/07/25 21:55:21
include_vm_objects_
danunez
2017/07/25 22:24:54
Done.
| |
| 82 | |
| 72 private: | 83 private: |
| 73 struct Node { | 84 struct Node { |
| 74 RawObject** ptr; // kSentinel for the sentinel node. | 85 RawObject** ptr; // kSentinel for the sentinel node. |
| 75 RawObject* obj; | 86 RawObject* obj; |
| 76 }; | 87 }; |
| 77 | 88 |
| 78 static RawObject** const kSentinel; | 89 static RawObject** const kSentinel; |
| 79 static const intptr_t kInitialCapacity = 1024; | 90 static const intptr_t kInitialCapacity = 1024; |
| 80 static const intptr_t kNoParent = -1; | 91 static const intptr_t kNoParent = -1; |
| 81 | 92 |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 }; | 381 }; |
| 371 | 382 |
| 372 intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) { | 383 intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) { |
| 373 NoSafepointScope no_safepoint_scope_; | 384 NoSafepointScope no_safepoint_scope_; |
| 374 HeapIterationScope iteration_scope(true); | 385 HeapIterationScope iteration_scope(true); |
| 375 // To break the trivial path, the handle 'obj' is temporarily cleared during | 386 // To break the trivial path, the handle 'obj' is temporarily cleared during |
| 376 // the search, but restored before returning. | 387 // the search, but restored before returning. |
| 377 RawObject* raw = obj->raw(); | 388 RawObject* raw = obj->raw(); |
| 378 *obj = Object::null(); | 389 *obj = Object::null(); |
| 379 RetainingPathVisitor visitor(raw, path); | 390 RetainingPathVisitor visitor(raw, path); |
| 380 IterateObjects(&visitor); | 391 IterateObjectsNoVM(&visitor); |
| 392 if (visitor.length() == 0) { | |
| 393 IterateObjects(&visitor); | |
| 394 } | |
| 381 *obj = raw; | 395 *obj = raw; |
| 382 return visitor.length(); | 396 return visitor.length(); |
| 383 } | 397 } |
| 384 | 398 |
| 385 class InboundReferencesVisitor : public ObjectVisitor, | 399 class InboundReferencesVisitor : public ObjectVisitor, |
| 386 public ObjectPointerVisitor { | 400 public ObjectPointerVisitor { |
| 387 public: | 401 public: |
| 388 // We cannot use a GrowableObjectArray, since we must not trigger GC. | 402 // We cannot use a GrowableObjectArray, since we must not trigger GC. |
| 389 InboundReferencesVisitor(Isolate* isolate, | 403 InboundReferencesVisitor(Isolate* isolate, |
| 390 RawObject* target, | 404 RawObject* target, |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 626 | 640 |
| 627 intptr_t object_count = visitor.count(); | 641 intptr_t object_count = visitor.count(); |
| 628 if (roots == kVM) { | 642 if (roots == kVM) { |
| 629 object_count += 1; // root | 643 object_count += 1; // root |
| 630 } else { | 644 } else { |
| 631 object_count += 2; // root and stack | 645 object_count += 2; // root and stack |
| 632 } | 646 } |
| 633 return object_count; | 647 return object_count; |
| 634 } | 648 } |
| 635 | 649 |
| 650 void ObjectGraph::IterateObjectsNoVM(ObjectGraph::Visitor* visitor) { | |
|
rmacnak
2017/07/25 21:55:21
Place next to ObjectGraph::IterateObjects.
danunez
2017/07/25 22:24:54
I can do this, but I will also have to move Iterat
| |
| 651 NoSafepointScope no_safepoint_scope_; | |
| 652 Stack stack(isolate()); | |
| 653 IterateUserFields(&stack); | |
| 654 stack.include_vm_obj = false; | |
| 655 stack.TraverseGraph(visitor); | |
| 656 Unmarker::UnmarkAll(isolate()); | |
| 657 } | |
| 658 | |
| 636 } // namespace dart | 659 } // namespace dart |
| OLD | NEW |