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 |