ART: Add correct field index to reference visiting

Use the created infrastructure to report references with the right
field indices.

Bug: 31385354
Test: m test-art-host-run-test-906-iterate-heap
Test: m test-art-host-run-test-913-heaps
Change-Id: I4647ea1bfe83dbce80c2fcb13ed1658527921f14
diff --git a/runtime/openjdkjvmti/ti_heap.cc b/runtime/openjdkjvmti/ti_heap.cc
index 5f59489..d52f0ea 100644
--- a/runtime/openjdkjvmti/ti_heap.cc
+++ b/runtime/openjdkjvmti/ti_heap.cc
@@ -171,15 +171,14 @@
   return false;
 }
 
-template <typename StaticPrimitiveVisitor,
-          typename StaticReferenceVisitor,
-          typename InstancePrimitiveVisitor,
-          typename InstanceReferenceVisitor,
-          typename UserData,
-          bool kCallVisitorOnRecursion>
+template <typename UserData, bool kCallVisitorOnRecursion>
 class FieldVisitor {
  public:
   // Report the contents of a primitive fields of the given object, if a callback is set.
+  template <typename StaticPrimitiveVisitor,
+            typename StaticReferenceVisitor,
+            typename InstancePrimitiveVisitor,
+            typename InstanceReferenceVisitor>
   static bool ReportFields(art::ObjPtr<art::mirror::Object> obj,
                            UserData* user_data,
                            StaticPrimitiveVisitor& static_prim_visitor,
@@ -223,6 +222,10 @@
 
   // Report the contents of fields of the given object. If obj is null, report the static fields,
   // otherwise the instance fields.
+  template <typename StaticPrimitiveVisitor,
+            typename StaticReferenceVisitor,
+            typename InstancePrimitiveVisitor,
+            typename InstanceReferenceVisitor>
   bool ReportFieldsImpl(art::ObjPtr<art::mirror::Object> obj,
                         art::ObjPtr<art::mirror::Class> klass,
                         bool skip_java_lang_object,
@@ -248,6 +251,10 @@
   }
 
   // Visit primitive fields in an object (instance). Return true if the visit was aborted.
+  template <typename StaticPrimitiveVisitor,
+            typename StaticReferenceVisitor,
+            typename InstancePrimitiveVisitor,
+            typename InstanceReferenceVisitor>
   bool ReportFieldsRecursive(art::ObjPtr<art::mirror::Object> obj,
                              art::ObjPtr<art::mirror::Class> klass,
                              size_t interface_fields,
@@ -432,31 +439,19 @@
 void DumpObjectFields(art::ObjPtr<art::mirror::Object> obj)
     REQUIRES_SHARED(art::Locks::mutator_lock_) {
   if (obj->IsClass()) {
-    FieldVisitor<decltype(DumpVisitor<true, false>::Callback),
-                 decltype(DumpVisitor<true, true>::Callback),
-                 decltype(DumpVisitor<false, false>::Callback),
-                 decltype(DumpVisitor<false, true>::Callback),
-                 void,
-                 false>::
-        ReportFields(obj,
-                     nullptr,
-                     DumpVisitor<true, false>::Callback,
-                     DumpVisitor<true, true>::Callback,
-                     DumpVisitor<false, false>::Callback,
-                     DumpVisitor<false, true>::Callback);
+    FieldVisitor<void, false>:: ReportFields(obj,
+                                             nullptr,
+                                             DumpVisitor<true, false>::Callback,
+                                             DumpVisitor<true, true>::Callback,
+                                             DumpVisitor<false, false>::Callback,
+                                             DumpVisitor<false, true>::Callback);
   } else {
-    FieldVisitor<decltype(DumpVisitor<true, false>::Callback),
-                 decltype(DumpVisitor<true, true>::Callback),
-                 decltype(DumpVisitor<false, false>::Callback),
-                 decltype(DumpVisitor<false, true>::Callback),
-                 void,
-                 true>::
-        ReportFields(obj,
-                     nullptr,
-                     DumpVisitor<true, false>::Callback,
-                     DumpVisitor<true, true>::Callback,
-                     DumpVisitor<false, false>::Callback,
-                     DumpVisitor<false, true>::Callback);
+    FieldVisitor<void, true>::ReportFields(obj,
+                                           nullptr,
+                                           DumpVisitor<true, false>::Callback,
+                                           DumpVisitor<true, true>::Callback,
+                                           DumpVisitor<false, false>::Callback,
+                                           DumpVisitor<false, true>::Callback);
   }
 }
 
@@ -471,31 +466,21 @@
       jlong class_tag = tag_table->GetTagOrZero(obj->GetClass());
       ReportPrimitiveField rpf(tag_table, class_tag, cb, user_data);
       if (obj->IsClass()) {
-        return FieldVisitor<decltype(ReportPrimitiveFieldCallback<true>),
-                            decltype(VisitorFalse<ReportPrimitiveField>),
-                            decltype(VisitorFalse<ReportPrimitiveField>),
-                            decltype(VisitorFalse<ReportPrimitiveField>),
-                            ReportPrimitiveField,
-                            false>::
-            ReportFields(obj,
-                         &rpf,
-                         ReportPrimitiveFieldCallback<true>,
-                         VisitorFalse<ReportPrimitiveField>,
-                         VisitorFalse<ReportPrimitiveField>,
-                         VisitorFalse<ReportPrimitiveField>);
+        return FieldVisitor<ReportPrimitiveField, false>::ReportFields(
+            obj,
+            &rpf,
+            ReportPrimitiveFieldCallback<true>,
+            VisitorFalse<ReportPrimitiveField>,
+            VisitorFalse<ReportPrimitiveField>,
+            VisitorFalse<ReportPrimitiveField>);
       } else {
-        return FieldVisitor<decltype(VisitorFalse<ReportPrimitiveField>),
-                            decltype(VisitorFalse<ReportPrimitiveField>),
-                            decltype(ReportPrimitiveFieldCallback<false>),
-                            decltype(VisitorFalse<ReportPrimitiveField>),
-                            ReportPrimitiveField,
-                            true>::
-            ReportFields(obj,
-                         &rpf,
-                         VisitorFalse<ReportPrimitiveField>,
-                         VisitorFalse<ReportPrimitiveField>,
-                         ReportPrimitiveFieldCallback<false>,
-                         VisitorFalse<ReportPrimitiveField>);
+        return FieldVisitor<ReportPrimitiveField, true>::ReportFields(
+            obj,
+            &rpf,
+            VisitorFalse<ReportPrimitiveField>,
+            VisitorFalse<ReportPrimitiveField>,
+            ReportPrimitiveFieldCallback<false>,
+            VisitorFalse<ReportPrimitiveField>);
       }
     }
     return false;
@@ -1006,68 +991,50 @@
       return;
     }
 
-    // TODO: We'll probably have to rewrite this completely with our own visiting logic, if we
-    //       want to have a chance of getting the field indices computed halfway efficiently. For
-    //       now, ignore them altogether.
-
-    struct InstanceReferenceVisitor {
-      explicit InstanceReferenceVisitor(FollowReferencesHelper* helper_)
-          : helper(helper_), stop_reports(false) {}
-
-      void operator()(art::mirror::Object* src,
-                      art::MemberOffset field_offset,
-                      bool is_static ATTRIBUTE_UNUSED) const
-          REQUIRES_SHARED(art::Locks::mutator_lock_)
-          REQUIRES(!*helper->tag_table_->GetAllowDisallowLock()) {
-        if (stop_reports) {
-          return;
-        }
-
-        art::mirror::Object* trg = src->GetFieldObjectReferenceAddr(field_offset)->AsMirrorPtr();
+    // All instance fields.
+    auto report_instance_field = [&](art::ObjPtr<art::mirror::Object> src,
+                                     art::ObjPtr<art::mirror::Class> obj_klass ATTRIBUTE_UNUSED,
+                                     art::ArtField& field,
+                                     size_t field_index,
+                                     void* user_data ATTRIBUTE_UNUSED)
+        REQUIRES_SHARED(art::Locks::mutator_lock_)
+        REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+      art::ObjPtr<art::mirror::Object> field_value = field.GetObject(src);
+      if (field_value != nullptr) {
         jvmtiHeapReferenceInfo reference_info;
         memset(&reference_info, 0, sizeof(reference_info));
 
         // TODO: Implement spec-compliant numbering.
-        reference_info.field.index = field_offset.Int32Value();
+        reference_info.field.index = field_index;
 
         jvmtiHeapReferenceKind kind =
-            field_offset.Int32Value() == art::mirror::Object::ClassOffset().Int32Value()
+            field.GetOffset().Int32Value() == art::mirror::Object::ClassOffset().Int32Value()
                 ? JVMTI_HEAP_REFERENCE_CLASS
                 : JVMTI_HEAP_REFERENCE_FIELD;
         const jvmtiHeapReferenceInfo* reference_info_ptr =
             kind == JVMTI_HEAP_REFERENCE_CLASS ? nullptr : &reference_info;
 
-        stop_reports = !helper->ReportReferenceMaybeEnqueue(kind, reference_info_ptr, src, trg);
+        return !ReportReferenceMaybeEnqueue(kind, reference_info_ptr, src.Ptr(), field_value.Ptr());
       }
-
-      void VisitRoot(art::mirror::CompressedReference<art::mirror::Object>* root ATTRIBUTE_UNUSED)
-          const {
-        LOG(FATAL) << "Unreachable";
-      }
-      void VisitRootIfNonNull(
-          art::mirror::CompressedReference<art::mirror::Object>* root ATTRIBUTE_UNUSED) const {
-        LOG(FATAL) << "Unreachable";
-      }
-
-      // "mutable" required by the visitor API.
-      mutable FollowReferencesHelper* helper;
-      mutable bool stop_reports;
+      return false;
     };
-
-    InstanceReferenceVisitor visitor(this);
-    // Visit references, not native roots.
-    obj->VisitReferences<false>(visitor, art::VoidFunctor());
-
-    stop_reports_ = visitor.stop_reports;
-
-    if (!stop_reports_) {
-      jint string_ret = ReportString(obj, env, tag_table_, callbacks_, user_data_);
-      stop_reports_ = (string_ret & JVMTI_VISIT_ABORT) != 0;
+    stop_reports_ = FieldVisitor<void, true>::ReportFields(obj,
+                                                           nullptr,
+                                                           VisitorFalse<void>,
+                                                           VisitorFalse<void>,
+                                                           VisitorFalse<void>,
+                                                           report_instance_field);
+    if (stop_reports_) {
+      return;
     }
 
-    if (!stop_reports_) {
-      stop_reports_ = ReportPrimitiveField::Report(obj, tag_table_, callbacks_, user_data_);
+    jint string_ret = ReportString(obj, env, tag_table_, callbacks_, user_data_);
+    stop_reports_ = (string_ret & JVMTI_VISIT_ABORT) != 0;
+    if (stop_reports_) {
+      return;
     }
+
+    stop_reports_ = ReportPrimitiveField::Report(obj, tag_table_, callbacks_, user_data_);
   }
 
   void VisitArray(art::mirror::Object* array)
@@ -1161,30 +1128,38 @@
     DCHECK_EQ(h_klass.Get(), klass);
 
     // Declared static fields.
-    for (auto& field : klass->GetSFields()) {
-      if (!field.IsPrimitiveType()) {
-        art::ObjPtr<art::mirror::Object> field_value = field.GetObject(klass);
-        if (field_value != nullptr) {
-          jvmtiHeapReferenceInfo reference_info;
-          memset(&reference_info, 0, sizeof(reference_info));
+    auto report_static_field = [&](art::ObjPtr<art::mirror::Object> obj ATTRIBUTE_UNUSED,
+                                   art::ObjPtr<art::mirror::Class> obj_klass,
+                                   art::ArtField& field,
+                                   size_t field_index,
+                                   void* user_data ATTRIBUTE_UNUSED)
+        REQUIRES_SHARED(art::Locks::mutator_lock_)
+        REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
+      art::ObjPtr<art::mirror::Object> field_value = field.GetObject(obj_klass);
+      if (field_value != nullptr) {
+        jvmtiHeapReferenceInfo reference_info;
+        memset(&reference_info, 0, sizeof(reference_info));
 
-          // TODO: Implement spec-compliant numbering.
-          reference_info.field.index = field.GetOffset().Int32Value();
+        reference_info.field.index = static_cast<jint>(field_index);
 
-          stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_STATIC_FIELD,
-                                                       &reference_info,
-                                                       klass,
-                                                       field_value.Ptr());
-          if (stop_reports_) {
-            return;
-          }
-        }
+        return !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_STATIC_FIELD,
+                                            &reference_info,
+                                            obj_klass.Ptr(),
+                                            field_value.Ptr());
       }
+      return false;
+    };
+    stop_reports_ = FieldVisitor<void, false>::ReportFields(klass,
+                                                            nullptr,
+                                                            VisitorFalse<void>,
+                                                            report_static_field,
+                                                            VisitorFalse<void>,
+                                                            VisitorFalse<void>);
+    if (stop_reports_) {
+      return;
     }
 
-    if (!stop_reports_) {
-      stop_reports_ = ReportPrimitiveField::Report(klass, tag_table_, callbacks_, user_data_);
-    }
+    stop_reports_ = ReportPrimitiveField::Report(klass, tag_table_, callbacks_, user_data_);
   }
 
   void MaybeEnqueue(art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
diff --git a/test/913-heaps/expected.txt b/test/913-heaps/expected.txt
index 437b7b8..fc2761e 100644
--- a/test/913-heaps/expected.txt
+++ b/test/913-heaps/expected.txt
@@ -8,34 +8,34 @@
 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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, 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]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 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]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, 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]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 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]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 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]
@@ -49,34 +49,34 @@
 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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, 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]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 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]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, 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]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 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]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 1@1000 [size=16, length=-1]
 6@1000 --(class)--> 1000@0 [size=123, length=-1]
 ---
 [1@0 (32, 'HelloWorld'), 2@0 (16, '')]
@@ -118,15 +118,15 @@
 --- klass ---
 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@8)--> 2@1000 [size=16, length=-1]
-3@1001 --(field@16)--> 4@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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 1@1000 [size=16, length=-1]
 ---
-1@1000 --(field@8)--> 2@1000 [size=16, length=-1]
-3@1001 --(field@16)--> 4@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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 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]
@@ -134,15 +134,15 @@
 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@8)--> 2@1000 [size=16, length=-1]
-3@1001 --(field@16)--> 4@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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 1@1000 [size=16, length=-1]
 ---
-1@1000 --(field@8)--> 2@1000 [size=16, length=-1]
-3@1001 --(field@16)--> 4@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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 1@1000 [size=16, length=-1]
 ---
 --- heap_filter ---
 ---- tagged objects
@@ -159,34 +159,34 @@
 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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, 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]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 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]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, 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]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 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]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 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]
@@ -200,34 +200,34 @@
 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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, 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]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 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]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 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]
+1@1000 --(field@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, 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]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 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]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 1@1000 [size=16, length=-1]
 6@1000 --(class)--> 1000@0 [size=123, length=-1]
 ---
 ---- tagged classes
@@ -281,19 +281,19 @@
 ---- 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@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=32, length=-1]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 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@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=32, length=-1]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 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]
@@ -301,17 +301,17 @@
 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@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=32, length=-1]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 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@2)--> 2@1000 [size=16, length=-1]
+1@1000 --(field@3)--> 3@1001 [size=24, length=-1]
+3@1001 --(field@4)--> 4@1000 [size=16, length=-1]
+3@1001 --(field@5)--> 5@1002 [size=32, length=-1]
+5@1002 --(field@8)--> 6@1000 [size=16, length=-1]
+5@1002 --(field@9)--> 1@1000 [size=16, length=-1]
 ---