From 4beab68986101d85d878491558bab34c9687beb0 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Mon, 20 Feb 2017 14:38:55 -0800 Subject: [PATCH] ART: Add heap filter support Add support for heap filter to FollowReferences. Update test. Bug: 31385354 Test: m test-art-host-run-test-913-heaps Change-Id: I09aa2076532c5fd2afecc77bf2e31e07174df0b2 --- runtime/openjdkjvmti/ti_heap.cc | 71 +++++++++------- test/913-heaps/expected.txt | 175 ++++++++++++++++++++++++++++++++++++++++ test/913-heaps/src/Main.java | 11 +++ 3 files changed, 230 insertions(+), 27 deletions(-) diff --git a/runtime/openjdkjvmti/ti_heap.cc b/runtime/openjdkjvmti/ti_heap.cc index eb2cbbd60..976ce66f1 100644 --- a/runtime/openjdkjvmti/ti_heap.cc +++ b/runtime/openjdkjvmti/ti_heap.cc @@ -159,32 +159,19 @@ jint ReportPrimitiveArray(art::ObjPtr obj, return 0; } -} // namespace - -struct IterateThroughHeapData { - IterateThroughHeapData(HeapUtil* _heap_util, - jvmtiEnv* _env, - jint heap_filter, - art::ObjPtr klass, - const jvmtiHeapCallbacks* _callbacks, - const void* _user_data) - : heap_util(_heap_util), - filter_klass(klass), - env(_env), - callbacks(_callbacks), - user_data(_user_data), - filter_out_tagged((heap_filter & JVMTI_HEAP_FILTER_TAGGED) != 0), +struct HeapFilter { + explicit HeapFilter(jint heap_filter) + : filter_out_tagged((heap_filter & JVMTI_HEAP_FILTER_TAGGED) != 0), filter_out_untagged((heap_filter & JVMTI_HEAP_FILTER_UNTAGGED) != 0), filter_out_class_tagged((heap_filter & JVMTI_HEAP_FILTER_CLASS_TAGGED) != 0), filter_out_class_untagged((heap_filter & JVMTI_HEAP_FILTER_CLASS_UNTAGGED) != 0), any_filter(filter_out_tagged || filter_out_untagged || filter_out_class_tagged || - filter_out_class_untagged), - stop_reports(false) { + filter_out_class_untagged) { } - bool ShouldReportByHeapFilter(jlong tag, jlong class_tag) { + bool ShouldReportByHeapFilter(jlong tag, jlong class_tag) const { if (!any_filter) { return true; } @@ -201,16 +188,37 @@ struct IterateThroughHeapData { return true; } - HeapUtil* heap_util; - art::ObjPtr filter_klass; - jvmtiEnv* env; - const jvmtiHeapCallbacks* callbacks; - const void* user_data; const bool filter_out_tagged; const bool filter_out_untagged; const bool filter_out_class_tagged; const bool filter_out_class_untagged; const bool any_filter; +}; + +} // namespace + +struct IterateThroughHeapData { + IterateThroughHeapData(HeapUtil* _heap_util, + jvmtiEnv* _env, + art::ObjPtr klass, + jint _heap_filter, + const jvmtiHeapCallbacks* _callbacks, + const void* _user_data) + : heap_util(_heap_util), + heap_filter(_heap_filter), + filter_klass(klass), + env(_env), + callbacks(_callbacks), + user_data(_user_data), + stop_reports(false) { + } + + HeapUtil* heap_util; + const HeapFilter heap_filter; + art::ObjPtr filter_klass; + jvmtiEnv* env; + const jvmtiHeapCallbacks* callbacks; + const void* user_data; bool stop_reports; }; @@ -233,7 +241,7 @@ static void IterateThroughHeapObjectCallback(art::mirror::Object* obj, void* arg ithd->heap_util->GetTags()->GetTag(klass.Ptr(), &class_tag); // For simplicity, even if we find a tag = 0, assume 0 = not tagged. - if (!ithd->ShouldReportByHeapFilter(tag, class_tag)) { + if (!ithd->heap_filter.ShouldReportByHeapFilter(tag, class_tag)) { return; } @@ -298,8 +306,8 @@ jvmtiError HeapUtil::IterateThroughHeap(jvmtiEnv* env, IterateThroughHeapData ithd(this, env, - heap_filter, soa.Decode(klass), + heap_filter, callbacks, user_data); @@ -315,12 +323,14 @@ class FollowReferencesHelper FINAL { art::ObjPtr initial_object, const jvmtiHeapCallbacks* callbacks, art::ObjPtr class_filter, + jint heap_filter, const void* user_data) : env(jvmti_env), tag_table_(h->GetTags()), initial_object_(initial_object), callbacks_(callbacks), class_filter_(class_filter), + heap_filter_(heap_filter), user_data_(user_data), start_(0), stop_reports_(false) { @@ -767,10 +777,15 @@ class FollowReferencesHelper FINAL { } const jlong class_tag = tag_table_->GetTagOrZero(referree->GetClass()); + jlong tag = tag_table_->GetTagOrZero(referree); + + if (!heap_filter_.ShouldReportByHeapFilter(tag, class_tag)) { + return JVMTI_VISIT_OBJECTS; + } + const jlong referrer_class_tag = referrer == nullptr ? 0 : tag_table_->GetTagOrZero(referrer->GetClass()); const jlong size = static_cast(referree->SizeOf()); - jlong tag = tag_table_->GetTagOrZero(referree); jlong saved_tag = tag; jlong referrer_tag = 0; jlong saved_referrer_tag = 0; @@ -816,6 +831,7 @@ class FollowReferencesHelper FINAL { art::ObjPtr initial_object_; const jvmtiHeapCallbacks* callbacks_; art::ObjPtr class_filter_; + const HeapFilter heap_filter_; const void* user_data_; std::vector worklist_; @@ -830,7 +846,7 @@ class FollowReferencesHelper FINAL { }; jvmtiError HeapUtil::FollowReferences(jvmtiEnv* env, - jint heap_filter ATTRIBUTE_UNUSED, + jint heap_filter, jclass klass, jobject initial_object, const jvmtiHeapCallbacks* callbacks, @@ -860,6 +876,7 @@ jvmtiError HeapUtil::FollowReferences(jvmtiEnv* env, self->DecodeJObject(initial_object), callbacks, class_filter, + heap_filter, user_data); frh.Init(); frh.Work(); diff --git a/test/913-heaps/expected.txt b/test/913-heaps/expected.txt index ff668dff9..f6bb99d78 100644 --- a/test/913-heaps/expected.txt +++ b/test/913-heaps/expected.txt @@ -119,3 +119,178 @@ root@root --(thread)--> 1@1000 [size=16, length=-1] 5@1002 --(field@24)--> 6@1000 [size=16, length=-1] 5@1002 --(field@28)--> 1@1000 [size=16, length=-1] --- +--- heap_filter --- +---- tagged objects +--- +--- +--- +--- +---- untagged objects +root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=13,location= 32])--> 1@1000 [size=16, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=3,method=doFollowReferencesTest,vreg=1,location= 28])--> 3000@0 [size=132, length=-1] +root@root --(system-class)--> 2@0 [size=40, 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=124, length=-1] +1002@0 --(superclass)--> 1001@0 [size=123, length=-1] +1@1000 --(class)--> 1000@0 [size=123, length=-1] +1@1000 --(field@12)--> 3@1001 [size=24, length=-1] +1@1000 --(field@8)--> 2@1000 [size=16, length=-1] +2001@0 --(interface)--> 2000@0 [size=124, length=-1] +2@1000 --(class)--> 1000@0 [size=123, length=-1] +3@1001 --(class)--> 1001@0 [size=123, length=-1] +3@1001 --(field@16)--> 4@1000 [size=16, length=-1] +3@1001 --(field@20)--> 5@1002 [size=32, length=-1] +4@1000 --(class)--> 1000@0 [size=123, length=-1] +5@1002 --(class)--> 1002@0 [size=123, length=-1] +5@1002 --(field@24)--> 6@1000 [size=16, length=-1] +5@1002 --(field@28)--> 1@1000 [size=16, length=-1] +6@1000 --(class)--> 1000@0 [size=123, length=-1] +--- +1001@0 --(superclass)--> 1000@0 [size=123, length=-1] +1002@0 --(interface)--> 2001@0 [size=124, length=-1] +1002@0 --(superclass)--> 1001@0 [size=123, length=-1] +1@1000 --(class)--> 1000@0 [size=123, length=-1] +1@1000 --(field@12)--> 3@1001 [size=24, length=-1] +1@1000 --(field@8)--> 2@1000 [size=16, length=-1] +2001@0 --(interface)--> 2000@0 [size=124, length=-1] +2@1000 --(class)--> 1000@0 [size=123, length=-1] +3@1001 --(class)--> 1001@0 [size=123, length=-1] +3@1001 --(field@16)--> 4@1000 [size=16, length=-1] +3@1001 --(field@20)--> 5@1002 [size=32, length=-1] +4@1000 --(class)--> 1000@0 [size=123, length=-1] +5@1002 --(class)--> 1002@0 [size=123, length=-1] +5@1002 --(field@24)--> 6@1000 [size=16, length=-1] +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[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=13,location= 10])--> 1@1000 [size=16, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 10])--> 1@1000 [size=16, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 19])--> 1@1000 [size=16, length=-1] +root@root --(system-class)--> 2@0 [size=40, length=-1] +root@root --(thread)--> 1@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=124, length=-1] +1002@0 --(superclass)--> 1001@0 [size=123, length=-1] +1@1000 --(class)--> 1000@0 [size=123, length=-1] +1@1000 --(field@12)--> 3@1001 [size=24, length=-1] +1@1000 --(field@8)--> 2@1000 [size=16, length=-1] +2001@0 --(interface)--> 2000@0 [size=124, length=-1] +2@1000 --(class)--> 1000@0 [size=123, length=-1] +3@1001 --(class)--> 1001@0 [size=123, length=-1] +3@1001 --(field@16)--> 4@1000 [size=16, length=-1] +3@1001 --(field@20)--> 5@1002 [size=32, length=-1] +4@1000 --(class)--> 1000@0 [size=123, length=-1] +5@1002 --(class)--> 1002@0 [size=123, length=-1] +5@1002 --(field@24)--> 6@1000 [size=16, length=-1] +5@1002 --(field@28)--> 1@1000 [size=16, length=-1] +6@1000 --(class)--> 1000@0 [size=123, length=-1] +--- +1001@0 --(superclass)--> 1000@0 [size=123, length=-1] +1002@0 --(interface)--> 2001@0 [size=124, length=-1] +1002@0 --(superclass)--> 1001@0 [size=123, length=-1] +1@1000 --(class)--> 1000@0 [size=123, length=-1] +1@1000 --(field@12)--> 3@1001 [size=24, length=-1] +1@1000 --(field@8)--> 2@1000 [size=16, length=-1] +2001@0 --(interface)--> 2000@0 [size=124, length=-1] +2@1000 --(class)--> 1000@0 [size=123, length=-1] +3@1001 --(class)--> 1001@0 [size=123, length=-1] +3@1001 --(field@16)--> 4@1000 [size=16, length=-1] +3@1001 --(field@20)--> 5@1002 [size=32, length=-1] +4@1000 --(class)--> 1000@0 [size=123, length=-1] +5@1002 --(class)--> 1002@0 [size=123, length=-1] +5@1002 --(field@24)--> 6@1000 [size=16, length=-1] +5@1002 --(field@28)--> 1@1000 [size=16, length=-1] +6@1000 --(class)--> 1000@0 [size=123, length=-1] +--- +---- tagged classes +root@root --(stack-local[id=1,tag=3000,depth=3,method=doFollowReferencesTest,vreg=1,location= 28])--> 3000@0 [size=132, length=-1] +root@root --(system-class)--> 2@0 [size=40, 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=124, length=-1] +1002@0 --(superclass)--> 1001@0 [size=123, length=-1] +1@1000 --(class)--> 1000@0 [size=123, length=-1] +2001@0 --(interface)--> 2000@0 [size=124, length=-1] +2@1000 --(class)--> 1000@0 [size=123, length=-1] +3@1001 --(class)--> 1001@0 [size=123, length=-1] +4@1000 --(class)--> 1000@0 [size=123, length=-1] +5@1002 --(class)--> 1002@0 [size=123, length=-1] +6@1000 --(class)--> 1000@0 [size=123, length=-1] +--- +1001@0 --(superclass)--> 1000@0 [size=123, length=-1] +1002@0 --(interface)--> 2001@0 [size=124, length=-1] +1002@0 --(superclass)--> 1001@0 [size=123, length=-1] +1@1000 --(class)--> 1000@0 [size=123, length=-1] +2001@0 --(interface)--> 2000@0 [size=124, length=-1] +2@1000 --(class)--> 1000@0 [size=123, length=-1] +3@1001 --(class)--> 1001@0 [size=123, length=-1] +4@1000 --(class)--> 1000@0 [size=123, length=-1] +5@1002 --(class)--> 1002@0 [size=123, length=-1] +6@1000 --(class)--> 1000@0 [size=123, length=-1] +--- +root@root --(system-class)--> 2@0 [size=40, 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=124, length=-1] +1002@0 --(superclass)--> 1001@0 [size=123, length=-1] +1@1000 --(class)--> 1000@0 [size=123, length=-1] +2001@0 --(interface)--> 2000@0 [size=124, length=-1] +2@1000 --(class)--> 1000@0 [size=123, length=-1] +3@1001 --(class)--> 1001@0 [size=123, length=-1] +4@1000 --(class)--> 1000@0 [size=123, length=-1] +5@1002 --(class)--> 1002@0 [size=123, length=-1] +6@1000 --(class)--> 1000@0 [size=123, length=-1] +--- +1001@0 --(superclass)--> 1000@0 [size=123, length=-1] +1002@0 --(interface)--> 2001@0 [size=124, length=-1] +1002@0 --(superclass)--> 1001@0 [size=123, length=-1] +1@1000 --(class)--> 1000@0 [size=123, length=-1] +2001@0 --(interface)--> 2000@0 [size=124, length=-1] +2@1000 --(class)--> 1000@0 [size=123, length=-1] +3@1001 --(class)--> 1001@0 [size=123, length=-1] +4@1000 --(class)--> 1000@0 [size=123, length=-1] +5@1002 --(class)--> 1002@0 [size=123, length=-1] +6@1000 --(class)--> 1000@0 [size=123, length=-1] +--- +---- untagged classes +root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=13,location= 32])--> 1@1000 [size=16, length=-1] +0@0 --(array-element@0)--> 1@1000 [size=16, length=-1] +1@1000 --(field@12)--> 3@1001 [size=24, length=-1] +1@1000 --(field@8)--> 2@1000 [size=16, length=-1] +3@1001 --(field@16)--> 4@1000 [size=16, length=-1] +3@1001 --(field@20)--> 5@1002 [size=32, length=-1] +5@1002 --(field@24)--> 6@1000 [size=16, length=-1] +5@1002 --(field@28)--> 1@1000 [size=16, length=-1] +--- +1@1000 --(field@12)--> 3@1001 [size=24, length=-1] +1@1000 --(field@8)--> 2@1000 [size=16, length=-1] +3@1001 --(field@16)--> 4@1000 [size=16, length=-1] +3@1001 --(field@20)--> 5@1002 [size=32, length=-1] +5@1002 --(field@24)--> 6@1000 [size=16, length=-1] +5@1002 --(field@28)--> 1@1000 [size=16, 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[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=13,location= 10])--> 1@1000 [size=16, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 10])--> 1@1000 [size=16, length=-1] +root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 19])--> 1@1000 [size=16, length=-1] +root@root --(thread)--> 1@1000 [size=16, length=-1] +1@1000 --(field@12)--> 3@1001 [size=24, length=-1] +1@1000 --(field@8)--> 2@1000 [size=16, length=-1] +3@1001 --(field@16)--> 4@1000 [size=16, length=-1] +3@1001 --(field@20)--> 5@1002 [size=32, length=-1] +5@1002 --(field@24)--> 6@1000 [size=16, length=-1] +5@1002 --(field@28)--> 1@1000 [size=16, length=-1] +--- +1@1000 --(field@12)--> 3@1001 [size=24, length=-1] +1@1000 --(field@8)--> 2@1000 [size=16, length=-1] +3@1001 --(field@16)--> 4@1000 [size=16, length=-1] +3@1001 --(field@20)--> 5@1002 [size=32, length=-1] +5@1002 --(field@24)--> 6@1000 [size=16, length=-1] +5@1002 --(field@28)--> 1@1000 [size=16, length=-1] +--- diff --git a/test/913-heaps/src/Main.java b/test/913-heaps/src/Main.java index 7a91d1f32..df89f347e 100644 --- a/test/913-heaps/src/Main.java +++ b/test/913-heaps/src/Main.java @@ -31,6 +31,17 @@ public class Main { // Test klass filter. System.out.println("--- klass ---"); new TestConfig(A.class, 0).doFollowReferencesTest(); + + // Test heap filter. + System.out.println("--- heap_filter ---"); + System.out.println("---- tagged objects"); + new TestConfig(null, 0x4).doFollowReferencesTest(); + System.out.println("---- untagged objects"); + new TestConfig(null, 0x8).doFollowReferencesTest(); + System.out.println("---- tagged classes"); + new TestConfig(null, 0x10).doFollowReferencesTest(); + System.out.println("---- untagged classes"); + new TestConfig(null, 0x20).doFollowReferencesTest(); } public static void doTest() throws Exception { -- 2.11.0