ART: Add JNI local details for FollowReferences

Give details for the thread.

Stack depth and method are currently approximated (as
bottom of the stack), as the RootInfo does not have that
information.

Bug: 31385354
Test: m test-art-host-run-test-913-heaps
Change-Id: I8e51415a02678c55b687144b4cb749c4105bd3c1
diff --git a/runtime/openjdkjvmti/ti_heap.cc b/runtime/openjdkjvmti/ti_heap.cc
index 0eff469..5e588a8 100644
--- a/runtime/openjdkjvmti/ti_heap.cc
+++ b/runtime/openjdkjvmti/ti_heap.cc
@@ -269,6 +269,12 @@
       ReportRoot(root_obj, info);
     }
 
+    // Remove NO_THREAD_SAFETY_ANALYSIS once ASSERT_CAPABILITY works correctly.
+    art::Thread* FindThread(const art::RootInfo& info) NO_THREAD_SAFETY_ANALYSIS {
+      art::Locks::thread_list_lock_->AssertExclusiveHeld(art::Thread::Current());
+      return art::Runtime::Current()->GetThreadList()->FindThreadByThreadId(info.GetThreadId());
+    }
+
     jvmtiHeapReferenceKind GetReferenceKind(const art::RootInfo& info,
                                             jvmtiHeapReferenceInfo* ref_info)
         REQUIRES_SHARED(art::Locks::mutator_lock_) {
@@ -280,7 +286,34 @@
           return JVMTI_HEAP_REFERENCE_JNI_GLOBAL;
 
         case art::RootType::kRootJNILocal:
+        {
+          uint32_t thread_id = info.GetThreadId();
+          ref_info->jni_local.thread_id = thread_id;
+
+          art::Thread* thread = FindThread(info);
+          if (thread != nullptr) {
+            art::mirror::Object* thread_obj = thread->GetPeer();
+            if (thread->IsStillStarting()) {
+              thread_obj = nullptr;
+            } else {
+              thread_obj = thread->GetPeer();
+            }
+            if (thread_obj != nullptr) {
+              ref_info->jni_local.thread_tag = tag_table_->GetTagOrZero(thread_obj);
+            }
+          }
+
+          // TODO: We don't have this info.
+          if (thread != nullptr) {
+            ref_info->jni_local.depth = 0;
+            art::ArtMethod* method = thread->GetCurrentMethod(nullptr, false /* abort_on_error */);
+            if (method != nullptr) {
+              ref_info->jni_local.method = art::jni::EncodeArtMethod(method);
+            }
+          }
+
           return JVMTI_HEAP_REFERENCE_JNI_LOCAL;
+        }
 
         case art::RootType::kRootJavaFrame:
           return JVMTI_HEAP_REFERENCE_STACK_LOCAL;