ART: Implement FollowReferences for initial object
Add code for FollowReferences with initial object. Simply skip
root visiting and add the initial object to the work list.
Bug: 31385354
Test: m test-art-host-run-test-913-heaps
Change-Id: I7d2a852fac54b13219df975d131f5b95e8094d9b
diff --git a/runtime/openjdkjvmti/ti_heap.cc b/runtime/openjdkjvmti/ti_heap.cc
index 5f18b7c..894cec2 100644
--- a/runtime/openjdkjvmti/ti_heap.cc
+++ b/runtime/openjdkjvmti/ti_heap.cc
@@ -174,10 +174,11 @@
class FollowReferencesHelper FINAL {
public:
FollowReferencesHelper(HeapUtil* h,
- art::ObjPtr<art::mirror::Object> initial_object ATTRIBUTE_UNUSED,
+ art::ObjPtr<art::mirror::Object> initial_object,
const jvmtiHeapCallbacks* callbacks,
const void* user_data)
: tag_table_(h->GetTags()),
+ initial_object_(initial_object),
callbacks_(callbacks),
user_data_(user_data),
start_(0),
@@ -187,13 +188,18 @@
void Init()
REQUIRES_SHARED(art::Locks::mutator_lock_)
REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
- CollectAndReportRootsVisitor carrv(this, tag_table_, &worklist_, &visited_);
- art::Runtime::Current()->VisitRoots(&carrv);
- art::Runtime::Current()->VisitImageRoots(&carrv);
- stop_reports_ = carrv.IsStopReports();
+ if (initial_object_.IsNull()) {
+ CollectAndReportRootsVisitor carrv(this, tag_table_, &worklist_, &visited_);
+ art::Runtime::Current()->VisitRoots(&carrv);
+ art::Runtime::Current()->VisitImageRoots(&carrv);
+ stop_reports_ = carrv.IsStopReports();
- if (stop_reports_) {
- worklist_.clear();
+ if (stop_reports_) {
+ worklist_.clear();
+ }
+ } else {
+ visited_.insert(initial_object_.Ptr());
+ worklist_.push_back(initial_object_.Ptr());
}
}
@@ -616,6 +622,7 @@
}
ObjectTagTable* tag_table_;
+ art::ObjPtr<art::mirror::Object> initial_object_;
const jvmtiHeapCallbacks* callbacks_;
const void* user_data_;
@@ -646,20 +653,28 @@
}
art::Thread* self = art::Thread::Current();
- art::ScopedObjectAccess soa(self); // Now we know we have the shared lock.
- art::Runtime::Current()->GetHeap()->IncrementDisableMovingGC(self);
+ art::gc::Heap* heap = art::Runtime::Current()->GetHeap();
+ if (heap->IsGcConcurrentAndMoving()) {
+ // Need to take a heap dump while GC isn't running. See the
+ // comment in Heap::VisitObjects().
+ heap->IncrementDisableMovingGC(self);
+ }
{
- art::ObjPtr<art::mirror::Object> o_initial = soa.Decode<art::mirror::Object>(initial_object);
-
+ art::ScopedObjectAccess soa(self); // Now we know we have the shared lock.
art::ScopedThreadSuspension sts(self, art::kWaitingForVisitObjects);
art::ScopedSuspendAll ssa("FollowReferences");
- FollowReferencesHelper frh(this, o_initial, callbacks, user_data);
+ FollowReferencesHelper frh(this,
+ self->DecodeJObject(initial_object),
+ callbacks,
+ user_data);
frh.Init();
frh.Work();
}
- art::Runtime::Current()->GetHeap()->DecrementDisableMovingGC(self);
+ if (heap->IsGcConcurrentAndMoving()) {
+ heap->DecrementDisableMovingGC(self);
+ }
return ERR(NONE);
}
diff --git a/test/913-heaps/expected.txt b/test/913-heaps/expected.txt
index 8002cfa..aba2a9a 100644
--- a/test/913-heaps/expected.txt
+++ b/test/913-heaps/expected.txt
@@ -21,12 +21,6 @@
5@1002 --(field@28)--> 1@1000 [size=16, length=-1]
6@1000 --(class)--> 1000@0 [size=123, length=-1]
---
-root@root --(stack-local)--> 1@1000 [size=16, length=-1]
-root@root --(stack-local)--> 2@1000 [size=16, length=-1]
-root@root --(stack-local)--> 3000@0 [size=132, length=-1]
-root@root --(thread)--> 2@1000 [size=16, length=-1]
-root@root --(thread)--> 3000@0 [size=132, length=-1]
-0@0 --(array-element@0)--> 1@1000 [size=16, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123, length=-1]
1002@0 --(interface)--> 2001@0 [size=132, length=-1]
1002@0 --(superclass)--> 1001@0 [size=123, length=-1]
@@ -66,13 +60,6 @@
5@1002 --(field@28)--> 1@1000 [size=16, length=-1]
6@1000 --(class)--> 1000@0 [size=123, length=-1]
---
-root@root --(jni-global)--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local)--> 1@1000 [size=16, length=-1]
-root@root --(stack-local)--> 2@1000 [size=16, length=-1]
-root@root --(thread)--> 1@1000 [size=16, length=-1]
-root@root --(thread)--> 2@1000 [size=16, length=-1]
-root@root --(thread)--> 3000@0 [size=132, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123, length=-1]
1002@0 --(interface)--> 2001@0 [size=132, length=-1]
1002@0 --(superclass)--> 1001@0 [size=123, length=-1]
diff --git a/test/913-heaps/src/Main.java b/test/913-heaps/src/Main.java
index a6ace9a..564596e 100644
--- a/test/913-heaps/src/Main.java
+++ b/test/913-heaps/src/Main.java
@@ -85,7 +85,7 @@
v.add("0@0", "1@1000"); // tmpStorage[0] --(array-element)--> a.
doFollowReferencesTestImpl(null, Integer.MAX_VALUE, -1, null, v, null);
- doFollowReferencesTestImpl(a.foo, Integer.MAX_VALUE, -1, null, v, "2@1000");
+ doFollowReferencesTestImpl(a.foo2, Integer.MAX_VALUE, -1, null, v, "3@1001");
tmpStorage.clear();
}
@@ -96,7 +96,7 @@
A a = createTree(v);
doFollowReferencesTestImpl(null, Integer.MAX_VALUE, -1, a, v, null);
- doFollowReferencesTestImpl(a.foo, Integer.MAX_VALUE, -1, a, v, "2@1000");
+ doFollowReferencesTestImpl(a.foo2, Integer.MAX_VALUE, -1, a, v, "3@1001");
}
private static void doFollowReferencesTestImpl(A root, int stopAfter, int followSet,