Add way to disable resolving for stack walk

Only occurs for walking the inlined frames case.

Bug: 27857910

Change-Id: Idb90254879ebae4c756ee1a3d235999ae589a2a8
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 5344cdd..116261b 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -39,6 +39,7 @@
 
 namespace art {
 
+template <bool kResolve = true>
 inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
                                     const InlineInfo& inline_info,
                                     uint8_t inlining_depth)
@@ -50,6 +51,9 @@
   if (!caller->IsRuntimeMethod()) {
     return caller;
   }
+  if (!kResolve) {
+    return nullptr;
+  }
 
   // The method in the dex cache can be the runtime method responsible for invoking
   // the stub that will then update the dex cache. Therefore, we need to do the
@@ -64,7 +68,7 @@
   if (inlining_depth == 0) {
     class_loader.Assign(outer_method->GetClassLoader());
   } else {
-    caller = GetResolvedMethod(outer_method, inline_info, inlining_depth - 1);
+    caller = GetResolvedMethod<kResolve>(outer_method, inline_info, inlining_depth - 1);
     class_loader.Assign(caller->GetClassLoader());
   }
 
diff --git a/runtime/gc/allocation_record.cc b/runtime/gc/allocation_record.cc
index 44059b1..bd023b3 100644
--- a/runtime/gc/allocation_record.cc
+++ b/runtime/gc/allocation_record.cc
@@ -187,7 +187,7 @@
  public:
   AllocRecordStackVisitor(Thread* thread, size_t max_depth, AllocRecordStackTrace* trace_out)
       SHARED_REQUIRES(Locks::mutator_lock_)
-      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+      : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFramesNoResolve),
         max_depth_(max_depth),
         trace_(trace_out) {}
 
@@ -198,7 +198,8 @@
       return false;
     }
     ArtMethod* m = GetMethod();
-    if (!m->IsRuntimeMethod()) {
+    // m may be null if we have inlined methods of unresolved classes. b/27858645
+    if (m != nullptr && !m->IsRuntimeMethod()) {
       m = m->GetInterfaceMethodIfProxy(sizeof(void*));
       trace_->AddStackElement(AllocRecordStackTraceElement(m, GetDexPc()));
     }
diff --git a/runtime/stack.cc b/runtime/stack.cc
index ee5da8e..57ce07d 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -130,7 +130,11 @@
     if (IsInInlinedFrame()) {
       size_t depth_in_stack_map = current_inlining_depth_ - 1;
       InlineInfo inline_info = GetCurrentInlineInfo();
-      return GetResolvedMethod(*GetCurrentQuickFrame(), inline_info, depth_in_stack_map);
+      DCHECK(walk_kind_ != StackWalkKind::kSkipInlinedFrames);
+      bool allow_resolve = walk_kind_ != StackWalkKind::kIncludeInlinedFramesNoResolve;
+      return allow_resolve
+          ? GetResolvedMethod<true>(*GetCurrentQuickFrame(), inline_info, depth_in_stack_map)
+          : GetResolvedMethod<false>(*GetCurrentQuickFrame(), inline_info, depth_in_stack_map);
     } else {
       return *cur_quick_frame_;
     }
@@ -859,7 +863,8 @@
         cur_oat_quick_method_header_ = method->GetOatQuickMethodHeader(cur_quick_frame_pc_);
         SanityCheckFrame();
 
-        if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames)
+        if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames ||
+             walk_kind_ == StackWalkKind::kIncludeInlinedFramesNoResolve)
             && (cur_oat_quick_method_header_ != nullptr)
             && cur_oat_quick_method_header_->IsOptimized()) {
           CodeInfo code_info = cur_oat_quick_method_header_->GetOptimizedCodeInfo();
diff --git a/runtime/stack.h b/runtime/stack.h
index 4fa1a4f..3659560 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -569,6 +569,7 @@
   // when walking the stack.
   enum class StackWalkKind {
     kIncludeInlinedFrames,
+    kIncludeInlinedFramesNoResolve,
     kSkipInlinedFrames,
   };