Remove depth argument from InlineInfo accessors in stack maps.

The InlineInfo class actually represented a list of inlining
information for a given stack map, and the depth argument was
used everywhere to select to desired element from the list.
This was verbose and inconsistent with the other classes.

Change the InlineInfo class to represent a single inlining,
and select the desired depth when getting it from CodeInfo.

Test: test-art-host-gtest-stack_map_test
Change-Id: I35b73e6704854f0203f51d4dbdbed5b1d1cd5a3b
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index f6b1c73..12e1397 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -46,22 +46,24 @@
 
 inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
                                     const MethodInfo& method_info,
-                                    const InlineInfo& inline_info,
+                                    const CodeInfo& code_info,
+                                    const StackMap& stack_map,
                                     uint8_t inlining_depth)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   DCHECK(!outer_method->IsObsolete());
+  InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, inlining_depth);
 
   // This method is being used by artQuickResolutionTrampoline, before it sets up
   // the passed parameters in a GC friendly way. Therefore we must never be
   // suspended while executing it.
   ScopedAssertNoThreadSuspension sants(__FUNCTION__);
 
-  if (inline_info.EncodesArtMethodAtDepth(inlining_depth)) {
-    return inline_info.GetArtMethodAtDepth(inlining_depth);
+  if (inline_info.EncodesArtMethod()) {
+    return inline_info.GetArtMethod();
   }
 
-  uint32_t method_index = inline_info.GetMethodIndexAtDepth(method_info, inlining_depth);
-  if (inline_info.GetDexPcAtDepth(inlining_depth) == static_cast<uint32_t>(-1)) {
+  uint32_t method_index = inline_info.GetMethodIndex(method_info);
+  if (inline_info.GetDexPc() == static_cast<uint32_t>(-1)) {
     // "charAt" special case. It is the only non-leaf method we inline across dex files.
     ArtMethod* inlined_method = jni::DecodeArtMethod(WellKnownClasses::java_lang_String_charAt);
     DCHECK_EQ(inlined_method->GetDexMethodIndex(), method_index);
@@ -72,9 +74,10 @@
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   ArtMethod* method = outer_method;
   for (uint32_t depth = 0, end = inlining_depth + 1u; depth != end; ++depth) {
-    DCHECK(!inline_info.EncodesArtMethodAtDepth(depth));
-    DCHECK_NE(inline_info.GetDexPcAtDepth(depth), static_cast<uint32_t>(-1));
-    method_index = inline_info.GetMethodIndexAtDepth(method_info, depth);
+    inline_info = code_info.GetInlineInfoAtDepth(stack_map, depth);
+    DCHECK(!inline_info.EncodesArtMethod());
+    DCHECK_NE(inline_info.GetDexPc(), static_cast<uint32_t>(-1));
+    method_index = inline_info.GetMethodIndex(method_info);
     ArtMethod* inlined_method = class_linker->LookupResolvedMethod(method_index,
                                                                    method->GetDexCache(),
                                                                    method->GetClassLoader());
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 7f9b385..e71d1fa 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -205,12 +205,9 @@
       MethodInfo method_info = current_code->GetOptimizedMethodInfo();
       StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
       DCHECK(stack_map.IsValid());
-      if (stack_map.HasInlineInfo()) {
-        InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
-        caller = GetResolvedMethod(outer_method,
-                                   method_info,
-                                   inline_info,
-                                   inline_info.GetDepth() - 1);
+      uint32_t depth = code_info.GetInlineDepthOf(stack_map);
+      if (depth != 0) {
+        caller = GetResolvedMethod(outer_method, method_info, code_info, stack_map, depth - 1);
       }
     }
     if (kIsDebugBuild && do_caller_check) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index a59faea..af6a936 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -344,9 +344,10 @@
       CodeInfo code_info(current_code);
       StackMap stack_map = code_info.GetStackMapForNativePcOffset(outer_pc_offset);
       DCHECK(stack_map.IsValid());
-      if (stack_map.HasInlineInfo()) {
-        InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
-        return inline_info.GetDexPcAtDepth(inline_info.GetDepth()-1);
+      uint32_t depth = code_info.GetInlineDepthOf(stack_map);
+      if (depth != 0) {
+        InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, depth - 1);
+        return inline_info.GetDexPc();
       } else {
         return stack_map.GetDexPc();
       }
@@ -1231,17 +1232,17 @@
   LOG(FATAL_WITHOUT_ABORT) << "  instruction: " << DumpInstruction(outer_method, dex_pc);
 
   ArtMethod* caller = outer_method;
-  if (stack_map.HasInlineInfo()) {
-    InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
-    size_t depth = inline_info.GetDepth();
+  uint32_t depth = code_info.GetInlineDepthOf(stack_map);
+  if (depth != 0) {
     for (size_t d = 0; d < depth; ++d) {
+      InlineInfo inline_info = code_info.GetInlineInfoAtDepth(stack_map, d);
       const char* tag = "";
-      dex_pc = inline_info.GetDexPcAtDepth(d);
-      if (inline_info.EncodesArtMethodAtDepth(d)) {
+      dex_pc = inline_info.GetDexPc();
+      if (inline_info.EncodesArtMethod()) {
         tag = "encoded ";
-        caller = inline_info.GetArtMethodAtDepth(d);
+        caller = inline_info.GetArtMethod();
       } else {
-        uint32_t method_index = inline_info.GetMethodIndexAtDepth(method_info, d);
+        uint32_t method_index = inline_info.GetMethodIndex(method_info);
         if (dex_pc == static_cast<uint32_t>(-1)) {
           tag = "special ";
           CHECK_EQ(d + 1u, depth);
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 4f4abf7..23ccf6a 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -406,7 +406,7 @@
     BitMemoryRegion stack_mask = code_info.GetStackMaskOf(stack_map);
     DexRegisterMap vreg_map = IsInInlinedFrame()
         ? code_info.GetDexRegisterMapAtDepth(GetCurrentInliningDepth() - 1,
-                                             code_info.GetInlineInfoOf(stack_map),
+                                             stack_map,
                                              number_of_vregs)
         : code_info.GetDexRegisterMapOf(stack_map, number_of_vregs);
 
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 6da7dcb..bd0d5d6 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -76,14 +76,14 @@
   }
 }
 
-static InlineInfo GetCurrentInlineInfo(CodeInfo& code_info,
-                                       const OatQuickMethodHeader* method_header,
-                                       uintptr_t cur_quick_frame_pc)
+static StackMap GetCurrentStackMap(CodeInfo& code_info,
+                                   const OatQuickMethodHeader* method_header,
+                                   uintptr_t cur_quick_frame_pc)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   uint32_t native_pc_offset = method_header->NativeQuickPcOffset(cur_quick_frame_pc);
   StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
   DCHECK(stack_map.IsValid());
-  return code_info.GetInlineInfoOf(stack_map);
+  return stack_map;
 }
 
 ArtMethod* StackVisitor::GetMethod() const {
@@ -94,14 +94,13 @@
       size_t depth_in_stack_map = current_inlining_depth_ - 1;
       const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
       CodeInfo code_info(method_header);
-      InlineInfo inline_info = GetCurrentInlineInfo(code_info,
-                                                    method_header,
-                                                    cur_quick_frame_pc_);
+      StackMap stack_map = GetCurrentStackMap(code_info, method_header, cur_quick_frame_pc_);
       MethodInfo method_info = method_header->GetOptimizedMethodInfo();
       DCHECK(walk_kind_ != StackWalkKind::kSkipInlinedFrames);
       return GetResolvedMethod(*GetCurrentQuickFrame(),
                                method_info,
-                               inline_info,
+                               code_info,
+                               stack_map,
                                depth_in_stack_map);
     } else {
       return *cur_quick_frame_;
@@ -118,8 +117,8 @@
       const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
       CodeInfo code_info(method_header);
       size_t depth_in_stack_map = current_inlining_depth_ - 1;
-      return GetCurrentInlineInfo(code_info, method_header, cur_quick_frame_pc_).
-          GetDexPcAtDepth(depth_in_stack_map);
+      StackMap stack_map = GetCurrentStackMap(code_info, method_header, cur_quick_frame_pc_);
+      return code_info.GetInlineInfoAtDepth(stack_map, depth_in_stack_map).GetDexPc();
     } else if (cur_oat_quick_method_header_ == nullptr) {
       return dex::kDexNoIndex;
     } else {
@@ -237,9 +236,7 @@
   size_t depth_in_stack_map = current_inlining_depth_ - 1;
 
   DexRegisterMap dex_register_map = IsInInlinedFrame()
-      ? code_info.GetDexRegisterMapAtDepth(depth_in_stack_map,
-                                           code_info.GetInlineInfoOf(stack_map),
-                                           number_of_dex_registers)
+      ? code_info.GetDexRegisterMapAtDepth(depth_in_stack_map, stack_map, number_of_dex_registers)
       : code_info.GetDexRegisterMapOf(stack_map, number_of_dex_registers);
 
   if (!dex_register_map.IsValid()) {
@@ -825,9 +822,8 @@
               cur_oat_quick_method_header_->NativeQuickPcOffset(cur_quick_frame_pc_);
           StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
           if (stack_map.IsValid() && stack_map.HasInlineInfo()) {
-            InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
             DCHECK_EQ(current_inlining_depth_, 0u);
-            for (current_inlining_depth_ = inline_info.GetDepth();
+            for (current_inlining_depth_ = code_info.GetInlineDepthOf(stack_map);
                  current_inlining_depth_ != 0;
                  --current_inlining_depth_) {
               bool should_continue = VisitFrame();
diff --git a/runtime/stack_map.cc b/runtime/stack_map.cc
index 923bb35..a5749b8 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -146,38 +146,39 @@
   }
   vios->Stream() << ")\n";
   DumpDexRegisterMap(vios, code_info.GetDexRegisterMapOf(*this, number_of_dex_registers));
-  if (HasInlineInfo()) {
-    InlineInfo inline_info = code_info.GetInlineInfoOf(*this);
+  uint32_t depth = code_info.GetInlineDepthOf(*this);
+  for (size_t d = 0; d < depth; d++) {
+    InlineInfo inline_info = code_info.GetInlineInfoAtDepth(*this, d);
     // We do not know the length of the dex register maps of inlined frames
     // at this level, so we just pass null to `InlineInfo::Dump` to tell
     // it not to look at these maps.
-    inline_info.Dump(vios, code_info, method_info, nullptr);
+    inline_info.Dump(vios, code_info, *this, method_info, 0);
   }
 }
 
 void InlineInfo::Dump(VariableIndentationOutputStream* vios,
                       const CodeInfo& code_info,
+                      const StackMap& stack_map,
                       const MethodInfo& method_info,
-                      uint16_t number_of_dex_registers[]) const {
-  for (size_t i = 0; i < GetDepth(); ++i) {
+                      uint16_t number_of_dex_registers) const {
+  uint32_t depth = Row() - stack_map.GetInlineInfoIndex();
+  vios->Stream()
+      << "InlineInfo[" << Row() << "]"
+      << " (depth=" << depth
+      << std::hex
+      << ", dex_pc=0x" << GetDexPc();
+  if (EncodesArtMethod()) {
+    ScopedObjectAccess soa(Thread::Current());
+    vios->Stream() << ", method=" << GetArtMethod()->PrettyMethod();
+  } else {
     vios->Stream()
-        << "InlineInfo[" << Row() + i << "]"
-        << " (depth=" << i
-        << std::hex
-        << ", dex_pc=0x" << GetDexPcAtDepth(i);
-    if (EncodesArtMethodAtDepth(i)) {
-      ScopedObjectAccess soa(Thread::Current());
-      vios->Stream() << ", method=" << GetArtMethodAtDepth(i)->PrettyMethod();
-    } else {
-      vios->Stream()
-          << std::dec
-          << ", method_index=" << GetMethodIndexAtDepth(method_info, i);
-    }
-    vios->Stream() << ")\n";
-    if (number_of_dex_registers != nullptr) {
-      uint16_t vregs = number_of_dex_registers[i];
-      DumpDexRegisterMap(vios, code_info.GetDexRegisterMapAtDepth(i, *this, vregs));
-    }
+        << std::dec
+        << ", method_index=" << GetMethodIndex(method_info);
+  }
+  vios->Stream() << ")\n";
+  if (number_of_dex_registers != 0) {
+    uint16_t vregs = number_of_dex_registers;
+    DumpDexRegisterMap(vios, code_info.GetDexRegisterMapAtDepth(depth, stack_map, vregs));
   }
 }
 
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 9aac204..b04197e 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -222,54 +222,47 @@
   InlineInfo(const BitTable<kCount>* table, uint32_t row)
     : BitTable<kCount>::Accessor(table, row) {}
 
-  ALWAYS_INLINE InlineInfo AtDepth(uint32_t depth) const {
-    return InlineInfo(table_, this->row_ + depth);
+  uint32_t GetIsLast() const { return Get<kIsLast>(); }
+
+  uint32_t GetMethodIndexIdx() const {
+    DCHECK(!EncodesArtMethod());
+    return Get<kMethodIndexIdx>();
   }
 
-  uint32_t GetDepth() const {
-    size_t depth = 0;
-    while (AtDepth(depth++).Get<kIsLast>() == kMore) { }
-    return depth;
+  uint32_t GetMethodIndex(const MethodInfo& method_info) const {
+    return method_info.GetMethodIndex(GetMethodIndexIdx());
   }
 
-  uint32_t GetMethodIndexIdxAtDepth(uint32_t depth) const {
-    DCHECK(!EncodesArtMethodAtDepth(depth));
-    return AtDepth(depth).Get<kMethodIndexIdx>();
+  uint32_t GetDexPc() const {
+    return Get<kDexPc>();
   }
 
-  uint32_t GetMethodIndexAtDepth(const MethodInfo& method_info, uint32_t depth) const {
-    return method_info.GetMethodIndex(GetMethodIndexIdxAtDepth(depth));
+  bool EncodesArtMethod() const {
+    return Get<kArtMethodLo>() != kNoValue;
   }
 
-  uint32_t GetDexPcAtDepth(uint32_t depth) const {
-    return AtDepth(depth).Get<kDexPc>();
-  }
-
-  bool EncodesArtMethodAtDepth(uint32_t depth) const {
-    return AtDepth(depth).Get<kArtMethodLo>() != kNoValue;
-  }
-
-  ArtMethod* GetArtMethodAtDepth(uint32_t depth) const {
-    uint64_t lo = AtDepth(depth).Get<kArtMethodLo>();
-    uint64_t hi = AtDepth(depth).Get<kArtMethodHi>();
+  ArtMethod* GetArtMethod() const {
+    uint64_t lo = Get<kArtMethodLo>();
+    uint64_t hi = Get<kArtMethodHi>();
     return reinterpret_cast<ArtMethod*>((hi << 32) | lo);
   }
 
-  uint32_t GetDexRegisterMaskIndexAtDepth(uint32_t depth) const {
-    return AtDepth(depth).Get<kDexRegisterMaskIndex>();
+  uint32_t GetDexRegisterMaskIndex() const {
+    return Get<kDexRegisterMaskIndex>();
   }
 
-  uint32_t GetDexRegisterMapIndexAtDepth(uint32_t depth) const {
-    return AtDepth(depth).Get<kDexRegisterMapIndex>();
+  uint32_t GetDexRegisterMapIndex() const {
+    return Get<kDexRegisterMapIndex>();
   }
-  bool HasDexRegisterMapAtDepth(uint32_t depth) const {
-    return GetDexRegisterMapIndexAtDepth(depth) != kNoValue;
+  bool HasDexRegisterMap() const {
+    return GetDexRegisterMapIndex() != kNoValue;
   }
 
   void Dump(VariableIndentationOutputStream* vios,
             const CodeInfo& info,
+            const StackMap& stack_map,
             const MethodInfo& method_info,
-            uint16_t* number_of_dex_registers) const;
+            uint16_t number_of_dex_registers) const;
 };
 
 class InvokeInfo : public BitTable<3>::Accessor {
@@ -417,10 +410,11 @@
   }
 
   ALWAYS_INLINE DexRegisterMap GetDexRegisterMapAtDepth(uint8_t depth,
-                                                        InlineInfo inline_info,
+                                                        StackMap stack_map,
                                                         size_t num_dex_registers) const {
-    return DecodeDexRegisterMap(inline_info.GetDexRegisterMaskIndexAtDepth(depth),
-                                inline_info.GetDexRegisterMapIndexAtDepth(depth),
+    InlineInfo inline_info = GetInlineInfoAtDepth(stack_map, depth);
+    return DecodeDexRegisterMap(inline_info.GetDexRegisterMaskIndex(),
+                                inline_info.GetDexRegisterMapIndex(),
                                 num_dex_registers);
   }
 
@@ -428,10 +422,19 @@
     return InlineInfo(&inline_infos_, index);
   }
 
-  InlineInfo GetInlineInfoOf(StackMap stack_map) const {
-    DCHECK(stack_map.HasInlineInfo());
+  uint32_t GetInlineDepthOf(StackMap stack_map) const {
+    uint32_t depth = 0;
     uint32_t index = stack_map.GetInlineInfoIndex();
-    return GetInlineInfo(index);
+    if (index != StackMap::kNoValue) {
+      while (GetInlineInfo(index + depth++).GetIsLast() == InlineInfo::kMore) { }
+    }
+    return depth;
+  }
+
+  InlineInfo GetInlineInfoAtDepth(StackMap stack_map, uint32_t depth) const {
+    DCHECK(stack_map.HasInlineInfo());
+    DCHECK_LT(depth, GetInlineDepthOf(stack_map));
+    return GetInlineInfo(stack_map.GetInlineInfoIndex() + depth);
   }
 
   StackMap GetStackMapForDexPc(uint32_t dex_pc) const {
@@ -473,7 +476,6 @@
                 stack_map.GetNativePcOffset(kRuntimeISA)) {
           DCHECK_EQ(other.GetDexRegisterMapIndex(),
                     stack_map.GetDexRegisterMapIndex());
-          DCHECK(!stack_map.HasInlineInfo());
           if (i < e - 2) {
             // Make sure there are not three identical stack maps following each other.
             DCHECK_NE(