| Index: runtime/vm/object_graph.cc
|
| ===================================================================
|
| --- runtime/vm/object_graph.cc (revision 36049)
|
| +++ runtime/vm/object_graph.cc (working copy)
|
| @@ -207,4 +207,50 @@
|
| return size_total - size_excluding_class;
|
| }
|
|
|
| +
|
| +class RetainingPathVisitor : public ObjectGraph::Visitor {
|
| + public:
|
| + // We cannot use a GrowableObjectArray, since we must not trigger GC.
|
| + RetainingPathVisitor(RawObject* obj, const Array& path)
|
| + : obj_(obj), path_(path), length_(0) {
|
| + ASSERT(Isolate::Current()->no_gc_scope_depth() != 0);
|
| + }
|
| +
|
| + intptr_t length() const { return length_; }
|
| +
|
| + virtual Direction VisitObject(ObjectGraph::StackIterator* it) {
|
| + if (it->Get() != obj_) {
|
| + return kProceed;
|
| + } else {
|
| + HANDLESCOPE(Isolate::Current());
|
| + Object& parent = Object::Handle();
|
| + for (length_ = 0; it->MoveToParent(); ++length_) {
|
| + if (!path_.IsNull() && length_ < path_.Length()) {
|
| + parent = it->Get();
|
| + path_.SetAt(length_, parent);
|
| + }
|
| + }
|
| + return kAbort;
|
| + }
|
| + }
|
| +
|
| + private:
|
| + RawObject* obj_;
|
| + const Array& path_;
|
| + intptr_t length_;
|
| +};
|
| +
|
| +
|
| +intptr_t ObjectGraph::RetainingPath(Object* obj, const Array& path) {
|
| + NoGCScope no_gc_scope_;
|
| + // To break the trivial path, the handle 'obj' is temporarily cleared during
|
| + // the search, but restored before returning.
|
| + RawObject* raw = obj->raw();
|
| + *obj = Object::null();
|
| + RetainingPathVisitor visitor(raw, path);
|
| + IterateObjects(&visitor);
|
| + *obj = raw;
|
| + return visitor.length();
|
| +}
|
| +
|
| } // namespace dart
|
|
|