Change MethodHelper to use a Handle.

Added ConstHandle to help prevent errors where you modify the value
stored in the handle of the caller. Also fixed compaction bugs
related to not knowing MethodHelper::GetReturnType can resolve types.
This bug was present in interpreter RETURN_OBJECT.

Bug: 13077697

Change-Id: I71f964d4d810ab4debda1a09bc968af8f3c874a3
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 5f4619b..8fcacc2 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -295,7 +295,9 @@
   if (UNLIKELY(entry_point == runtime->GetClassLinker()->GetQuickGenericJniTrampoline())) {
     // Generic JNI frame.
     DCHECK(IsNative());
-    uint32_t handle_refs = MethodHelper(this).GetNumberOfReferenceArgsWithoutReceiver() + 1;
+    StackHandleScope<1> hs(Thread::Current());
+    uint32_t handle_refs =
+        MethodHelper(hs.NewHandle(this)).GetNumberOfReferenceArgsWithoutReceiver() + 1;
     size_t scope_size = HandleScope::SizeOf(handle_refs);
     QuickMethodFrameInfo callee_info = runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
 
@@ -314,10 +316,143 @@
 
 inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo(const void* code_pointer) {
   DCHECK(code_pointer != nullptr);
-  DCHECK(code_pointer == GetQuickOatCodePointer());
+  DCHECK_EQ(code_pointer, GetQuickOatCodePointer());
   return reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].frame_info_;
 }
 
+inline const DexFile* ArtMethod::GetDexFile() {
+  return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache()->GetDexFile();
+}
+
+inline const char* ArtMethod::GetDeclaringClassDescriptor() {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  uint32_t dex_method_idx = method->GetDexMethodIndex();
+  if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
+    return "<runtime method>";
+  }
+  const DexFile* dex_file = method->GetDexFile();
+  return dex_file->GetMethodDeclaringClassDescriptor(dex_file->GetMethodId(dex_method_idx));
+}
+
+inline const char* ArtMethod::GetShorty(uint32_t* out_length) {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  const DexFile* dex_file = method->GetDexFile();
+  return dex_file->GetMethodShorty(dex_file->GetMethodId(method->GetDexMethodIndex()), out_length);
+}
+
+inline const Signature ArtMethod::GetSignature() {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  uint32_t dex_method_idx = method->GetDexMethodIndex();
+  if (dex_method_idx != DexFile::kDexNoIndex) {
+    const DexFile* dex_file = method->GetDexFile();
+    return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx));
+  }
+  return Signature::NoSignature();
+}
+
+inline const char* ArtMethod::GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  uint32_t dex_method_idx = method->GetDexMethodIndex();
+  if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) {
+    const DexFile* dex_file = method->GetDexFile();
+    return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx));
+  }
+  Runtime* runtime = Runtime::Current();
+  if (method == runtime->GetResolutionMethod()) {
+    return "<runtime internal resolution method>";
+  } else if (method == runtime->GetImtConflictMethod()) {
+    return "<runtime internal imt conflict method>";
+  } else if (method == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) {
+    return "<runtime internal callee-save all registers method>";
+  } else if (method == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) {
+    return "<runtime internal callee-save reference registers method>";
+  } else if (method == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) {
+    return "<runtime internal callee-save reference and argument registers method>";
+  } else {
+    return "<unknown runtime internal method>";
+  }
+}
+
+inline const DexFile::CodeItem* ArtMethod::GetCodeItem() {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  return method->GetDexFile()->GetCodeItem(method->GetCodeItemOffset());
+}
+
+inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  return method->GetDexCacheResolvedTypes()->Get(type_idx) != nullptr;
+}
+
+inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  if (dex_pc == DexFile::kDexNoIndex) {
+    return method->IsNative() ? -2 : -1;
+  }
+  return method->GetDexFile()->GetLineNumFromPC(method, dex_pc);
+}
+
+inline const DexFile::ProtoId& ArtMethod::GetPrototype() {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  const DexFile* dex_file = method->GetDexFile();
+  return dex_file->GetMethodPrototype(dex_file->GetMethodId(method->GetDexMethodIndex()));
+}
+
+inline const DexFile::TypeList* ArtMethod::GetParameterTypeList() {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  const DexFile* dex_file = method->GetDexFile();
+  const DexFile::ProtoId& proto = dex_file->GetMethodPrototype(
+      dex_file->GetMethodId(method->GetDexMethodIndex()));
+  return dex_file->GetProtoParameters(proto);
+}
+
+inline const char* ArtMethod::GetDeclaringClassSourceFile() {
+  return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetSourceFile();
+}
+
+inline uint16_t ArtMethod::GetClassDefIndex() {
+  return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexClassDefIndex();
+}
+
+inline const DexFile::ClassDef& ArtMethod::GetClassDef() {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  return method->GetDexFile()->GetClassDef(GetClassDefIndex());
+}
+
+inline const char* ArtMethod::GetReturnTypeDescriptor() {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  const DexFile* dex_file = method->GetDexFile();
+  const DexFile::MethodId& method_id = dex_file->GetMethodId(method->GetDexMethodIndex());
+  const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
+  uint16_t return_type_idx = proto_id.return_type_idx_;
+  return dex_file->GetTypeDescriptor(dex_file->GetTypeId(return_type_idx));
+}
+
+inline const char* ArtMethod::GetTypeDescriptorFromTypeIdx(uint16_t type_idx) {
+  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  const DexFile* dex_file = method->GetDexFile();
+  return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx));
+}
+
+inline mirror::ClassLoader* ArtMethod::GetClassLoader() {
+  return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetClassLoader();
+}
+
+inline mirror::DexCache* ArtMethod::GetDexCache() {
+  return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache();
+}
+
+inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy() {
+  mirror::Class* klass = GetDeclaringClass();
+  if (LIKELY(!klass->IsProxyClass())) {
+    return this;
+  }
+  mirror::ArtMethod* interface_method = GetDexCacheResolvedMethods()->Get(GetDexMethodIndex());
+  DCHECK(interface_method != nullptr);
+  DCHECK_EQ(interface_method,
+            Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this));
+  return interface_method;
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index c01fc72..3db4be3 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -142,16 +142,16 @@
       CHECK_EQ(result,
                Runtime::Current()->GetClassLinker()->FindMethodForProxy(GetDeclaringClass(), this));
     } else {
-      MethodHelper mh(this);
-      MethodHelper interface_mh;
+      StackHandleScope<2> hs(Thread::Current());
+      MethodHelper mh(hs.NewHandle(this));
+      MethodHelper interface_mh(hs.NewHandle<mirror::ArtMethod>(nullptr));
       IfTable* iftable = GetDeclaringClass()->GetIfTable();
       for (size_t i = 0; i < iftable->Count() && result == NULL; i++) {
         Class* interface = iftable->GetInterface(i);
         for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
-          ArtMethod* interface_method = interface->GetVirtualMethod(j);
-          interface_mh.ChangeMethod(interface_method);
+          interface_mh.ChangeMethod(interface->GetVirtualMethod(j));
           if (mh.HasSameNameAndSignature(&interface_mh)) {
-            result = interface_method;
+            result = interface_mh.GetMethod();
             break;
           }
         }
@@ -159,8 +159,10 @@
     }
   }
 #ifndef NDEBUG
-  MethodHelper result_mh(result);
-  DCHECK(result == NULL || MethodHelper(this).HasSameNameAndSignature(&result_mh));
+  StackHandleScope<2> hs(Thread::Current());
+  MethodHelper result_mh(hs.NewHandle(result));
+  MethodHelper this_mh(hs.NewHandle(this));
+  DCHECK(result == NULL || this_mh.HasSameNameAndSignature(&result_mh));
 #endif
   return result;
 }
@@ -229,10 +231,10 @@
   return 0;
 }
 
-uint32_t ArtMethod::FindCatchBlock(Handle<Class> exception_type, uint32_t dex_pc,
-                                   bool* has_no_move_exception) {
-  MethodHelper mh(this);
-  const DexFile::CodeItem* code_item = mh.GetCodeItem();
+uint32_t ArtMethod::FindCatchBlock(Handle<ArtMethod> h_this, Handle<Class> exception_type,
+                                   uint32_t dex_pc, bool* has_no_move_exception) {
+  MethodHelper mh(h_this);
+  const DexFile::CodeItem* code_item = h_this->GetCodeItem();
   // Set aside the exception while we resolve its type.
   Thread* self = Thread::Current();
   ThrowLocation throw_location;
@@ -260,7 +262,7 @@
       // release its in use context at the end.
       delete self->GetLongJumpContext();
       LOG(WARNING) << "Unresolved exception class when finding catch block: "
-        << DescriptorToDot(mh.GetTypeDescriptorFromTypeIdx(iter_type_idx));
+        << DescriptorToDot(h_this->GetTypeDescriptorFromTypeIdx(iter_type_idx));
     } else if (iter_exception_type->IsAssignableFrom(exception_type.Get())) {
       found_dex_pc = it.GetHandlerAddress();
       break;
@@ -283,7 +285,7 @@
   if (kIsDebugBuild) {
     self->AssertThreadSuspensionIsAllowable();
     CHECK_EQ(kRunnable, self->GetState());
-    CHECK_STREQ(MethodHelper(this).GetShorty(), shorty);
+    CHECK_STREQ(GetShorty(), shorty);
   }
 
   // Push a transition back into managed code onto the linked list in thread.
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index f901512..1c21b81 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -88,6 +88,11 @@
     return (GetAccessFlags() & kAccConstructor) != 0;
   }
 
+  // Returns true if the method is a class initializer.
+  bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return IsConstructor() && IsStatic();
+  }
+
   // Returns true if the method is static, private, or a constructor.
   bool IsDirect() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return IsDirect(GetAccessFlags());
@@ -216,14 +221,14 @@
   // Find the method that this method overrides
   ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
-              const char* shorty) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, const char* shorty)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   EntryPointFromInterpreter* GetEntryPointFromInterpreter()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return GetFieldPtr<EntryPointFromInterpreter*, kVerifyFlags>(
-               OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_));
+        OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_));
   }
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -281,7 +286,7 @@
      *
      * NOTE: For Thumb both pc and code are offset by 1 indicating the Thumb state.
      */
-    return (code <= pc && pc <= code + GetCodeSize());
+    return code <= pc && pc <= code + GetCodeSize();
   }
 
   void AssertPcIsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -398,8 +403,8 @@
   // Find the catch block for the given exception type and dex_pc. When a catch block is found,
   // indicates whether the found catch block is responsible for clearing the exception or whether
   // a move-exception instruction is present.
-  uint32_t FindCatchBlock(Handle<Class> exception_type, uint32_t dex_pc,
-                          bool* has_no_move_exception)
+  static uint32_t FindCatchBlock(Handle<ArtMethod> h_this, Handle<Class> exception_type,
+                                 uint32_t dex_pc, bool* has_no_move_exception)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void SetClass(Class* java_lang_reflect_ArtMethod);
@@ -414,6 +419,30 @@
   static void VisitRoots(RootCallback* callback, void* arg)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  const DexFile* GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const char* GetDeclaringClassDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const char* GetShorty() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    uint32_t unused_length;
+    return GetShorty(&unused_length);
+  }
+  const char* GetShorty(uint32_t* out_length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const Signature GetSignature() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const char* GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const DexFile::CodeItem* GetCodeItem() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool IsResolvedTypeIdx(uint16_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  int32_t GetLineNumFromDexPC(uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const DexFile::ProtoId& GetPrototype() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const DexFile::TypeList* GetParameterTypeList() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const char* GetDeclaringClassSourceFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  uint16_t GetClassDefIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const DexFile::ClassDef& GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const char* GetReturnTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  mirror::ClassLoader* GetClassLoader() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* GetInterfaceMethodIfProxy() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  protected:
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   // The class we are a part of.
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index a409093..7b31a82 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -366,11 +366,9 @@
 }
 
 ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) {
-  MethodHelper mh;
   for (size_t i = 0; i < NumDirectMethods(); ++i) {
     ArtMethod* method = GetDirectMethod(i);
-    mh.ChangeMethod(method);
-    if (name == mh.GetName() && mh.GetSignature() == signature) {
+    if (name == method->GetName() && method->GetSignature() == signature) {
       return method;
     }
   }
@@ -378,11 +376,9 @@
 }
 
 ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) {
-  MethodHelper mh;
   for (size_t i = 0; i < NumDirectMethods(); ++i) {
     ArtMethod* method = GetDirectMethod(i);
-    mh.ChangeMethod(method);
-    if (name == mh.GetName() && signature == mh.GetSignature()) {
+    if (name == method->GetName() && signature == method->GetSignature()) {
       return method;
     }
   }
@@ -432,24 +428,19 @@
 }
 
 ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) {
-  MethodHelper mh;
   for (size_t i = 0; i < NumVirtualMethods(); ++i) {
     ArtMethod* method = GetVirtualMethod(i);
-    mh.ChangeMethod(method);
-    if (name == mh.GetName() && mh.GetSignature() == signature) {
+    if (name == method->GetName() && method->GetSignature() == signature) {
       return method;
     }
   }
   return NULL;
 }
 
-ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name,
-                                            const Signature& signature) {
-  MethodHelper mh;
+ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature) {
   for (size_t i = 0; i < NumVirtualMethods(); ++i) {
     ArtMethod* method = GetVirtualMethod(i);
-    mh.ChangeMethod(method);
-    if (name == mh.GetName() && signature == mh.GetSignature()) {
+    if (name == method->GetName() && signature == method->GetSignature()) {
       return method;
     }
   }
@@ -501,13 +492,9 @@
 ArtMethod* Class::FindClassInitializer() {
   for (size_t i = 0; i < NumDirectMethods(); ++i) {
     ArtMethod* method = GetDirectMethod(i);
-    if (method->IsConstructor() && method->IsStatic()) {
-      if (kIsDebugBuild) {
-        MethodHelper mh(method);
-        CHECK(mh.IsClassInitializer());
-        CHECK_STREQ(mh.GetName(), "<clinit>");
-        CHECK_STREQ(mh.GetSignature().ToString().c_str(), "()V");
-      }
+    if (method->IsClassInitializer()) {
+      DCHECK_STREQ(method->GetName(), "<clinit>");
+      DCHECK_STREQ(method->GetSignature().ToString().c_str(), "()V");
       return method;
     }
   }
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 18e50ce..f85fb27 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -451,7 +451,7 @@
 
   jobject jclass_loader_1 = LoadDex("ProtoCompare");
   jobject jclass_loader_2 = LoadDex("ProtoCompare2");
-  StackHandleScope<2> hs(soa.Self());
+  StackHandleScope<4> hs(soa.Self());
   Handle<ClassLoader> class_loader_1(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader_1)));
   Handle<ClassLoader> class_loader_2(hs.NewHandle(soa.Decode<ClassLoader*>(jclass_loader_2)));
 
@@ -461,33 +461,25 @@
   ASSERT_TRUE(klass2 != NULL);
 
   ArtMethod* m1_1 = klass1->GetVirtualMethod(0);
-  MethodHelper mh(m1_1);
-  EXPECT_STREQ(mh.GetName(), "m1");
+  EXPECT_STREQ(m1_1->GetName(), "m1");
   ArtMethod* m2_1 = klass1->GetVirtualMethod(1);
-  mh.ChangeMethod(m2_1);
-  EXPECT_STREQ(mh.GetName(), "m2");
+  EXPECT_STREQ(m2_1->GetName(), "m2");
   ArtMethod* m3_1 = klass1->GetVirtualMethod(2);
-  mh.ChangeMethod(m3_1);
-  EXPECT_STREQ(mh.GetName(), "m3");
+  EXPECT_STREQ(m3_1->GetName(), "m3");
   ArtMethod* m4_1 = klass1->GetVirtualMethod(3);
-  mh.ChangeMethod(m4_1);
-  EXPECT_STREQ(mh.GetName(), "m4");
+  EXPECT_STREQ(m4_1->GetName(), "m4");
 
   ArtMethod* m1_2 = klass2->GetVirtualMethod(0);
-  mh.ChangeMethod(m1_2);
-  EXPECT_STREQ(mh.GetName(), "m1");
+  EXPECT_STREQ(m1_2->GetName(), "m1");
   ArtMethod* m2_2 = klass2->GetVirtualMethod(1);
-  mh.ChangeMethod(m2_2);
-  EXPECT_STREQ(mh.GetName(), "m2");
+  EXPECT_STREQ(m2_2->GetName(), "m2");
   ArtMethod* m3_2 = klass2->GetVirtualMethod(2);
-  mh.ChangeMethod(m3_2);
-  EXPECT_STREQ(mh.GetName(), "m3");
+  EXPECT_STREQ(m3_2->GetName(), "m3");
   ArtMethod* m4_2 = klass2->GetVirtualMethod(3);
-  mh.ChangeMethod(m4_2);
-  EXPECT_STREQ(mh.GetName(), "m4");
+  EXPECT_STREQ(m4_2->GetName(), "m4");
 
-  mh.ChangeMethod(m1_1);
-  MethodHelper mh2(m1_2);
+  MethodHelper mh(hs.NewHandle(m1_1));
+  MethodHelper mh2(hs.NewHandle(m1_2));
   EXPECT_TRUE(mh.HasSameNameAndSignature(&mh2));
   EXPECT_TRUE(mh2.HasSameNameAndSignature(&mh));
 
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index 6874fe5..6efc9e2 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -85,16 +85,14 @@
     ObjectArray<Object>* method_trace = down_cast<ObjectArray<Object>*>(stack_state);
     int32_t depth = method_trace->GetLength() - 1;
     IntArray* pc_trace = down_cast<IntArray*>(method_trace->Get(depth));
-    MethodHelper mh;
     if (depth == 0) {
       result += "(Throwable with empty stack trace)";
     } else {
       for (int32_t i = 0; i < depth; ++i) {
-        ArtMethod* method = down_cast<ArtMethod*>(method_trace->Get(i));
-        mh.ChangeMethod(method);
+        mirror::ArtMethod* method = down_cast<ArtMethod*>(method_trace->Get(i));
         uint32_t dex_pc = pc_trace->Get(i);
-        int32_t line_number = mh.GetLineNumFromDexPC(dex_pc);
-        const char* source_file = mh.GetDeclaringClassSourceFile();
+        int32_t line_number = method->GetLineNumFromDexPC(dex_pc);
+        const char* source_file = method->GetDeclaringClassSourceFile();
         result += StringPrintf("  at %s (%s:%d)\n", PrettyMethod(method, true).c_str(),
                                source_file, line_number);
       }