Merge "Move mirror::ArtMethod to native"
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 5a9e04f..0a1e2e3 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -17,6 +17,8 @@
 #include "common_compiler_test.h"
 
 #include "arch/instruction_set_features.h"
+#include "art_field-inl.h"
+#include "art_method.h"
 #include "class_linker.h"
 #include "compiled_method.h"
 #include "dex/pass_manager.h"
@@ -26,7 +28,8 @@
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
 #include "interpreter/interpreter.h"
-#include "mirror/art_method.h"
+#include "mirror/class_loader.h"
+#include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
 #include "mirror/object-inl.h"
 #include "scoped_thread_state_change.h"
@@ -38,7 +41,7 @@
 CommonCompilerTest::CommonCompilerTest() {}
 CommonCompilerTest::~CommonCompilerTest() {}
 
-void CommonCompilerTest::MakeExecutable(mirror::ArtMethod* method) {
+void CommonCompilerTest::MakeExecutable(ArtMethod* method) {
   CHECK(method != nullptr);
 
   const CompiledMethod* compiled_method = nullptr;
@@ -132,11 +135,12 @@
   Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
   mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
   CHECK(klass != nullptr) << "Class not found " << class_name;
-  for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-    MakeExecutable(klass->GetDirectMethod(i));
+  size_t pointer_size = class_linker_->GetImagePointerSize();
+  for (auto& m : klass->GetDirectMethods(pointer_size)) {
+    MakeExecutable(&m);
   }
-  for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
-    MakeExecutable(klass->GetVirtualMethod(i));
+  for (auto& m : klass->GetVirtualMethods(pointer_size)) {
+    MakeExecutable(&m);
   }
 }
 
@@ -225,15 +229,16 @@
   Handle<mirror::ClassLoader> loader(hs.NewHandle(class_loader));
   mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
   CHECK(klass != nullptr) << "Class not found " << class_name;
-  for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-    CompileMethod(klass->GetDirectMethod(i));
+  auto pointer_size = class_linker_->GetImagePointerSize();
+  for (auto& m : klass->GetDirectMethods(pointer_size)) {
+    CompileMethod(&m);
   }
-  for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
-    CompileMethod(klass->GetVirtualMethod(i));
+  for (auto& m : klass->GetVirtualMethods(pointer_size)) {
+    CompileMethod(&m);
   }
 }
 
-void CommonCompilerTest::CompileMethod(mirror::ArtMethod* method) {
+void CommonCompilerTest::CompileMethod(ArtMethod* method) {
   CHECK(method != nullptr);
   TimingLogger timings("CommonTest::CompileMethod", false, false);
   TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
@@ -249,7 +254,8 @@
   Thread* self = Thread::Current();
   mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
   CHECK(klass != nullptr) << "Class not found " << class_name;
-  mirror::ArtMethod* method = klass->FindDirectMethod(method_name, signature);
+  auto pointer_size = class_linker_->GetImagePointerSize();
+  ArtMethod* method = klass->FindDirectMethod(method_name, signature, pointer_size);
   CHECK(method != nullptr) << "Direct method not found: "
       << class_name << "." << method_name << signature;
   CompileMethod(method);
@@ -262,7 +268,8 @@
   Thread* self = Thread::Current();
   mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), class_loader);
   CHECK(klass != nullptr) << "Class not found " << class_name;
-  mirror::ArtMethod* method = klass->FindVirtualMethod(method_name, signature);
+  auto pointer_size = class_linker_->GetImagePointerSize();
+  ArtMethod* method = klass->FindVirtualMethod(method_name, signature, pointer_size);
   CHECK(method != nullptr) << "Virtual method not found: "
       << class_name << "." << method_name << signature;
   CompileMethod(method);
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 8d80a2d..769319b 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -45,7 +45,7 @@
   // Create an OatMethod based on pointers (for unit tests).
   OatFile::OatMethod CreateOatMethod(const void* code);
 
-  void MakeExecutable(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void MakeExecutable(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void MakeExecutable(const void* code_start, size_t code_length);
 
@@ -74,7 +74,7 @@
   void CompileClass(mirror::ClassLoader* class_loader, const char* class_name)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void CompileMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void CompileMethod(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void CompileDirectMethod(Handle<mirror::ClassLoader> class_loader, const char* class_name,
                            const char* method_name, const char* signature)
diff --git a/compiler/compiler.h b/compiler/compiler.h
index 94b0fe3..e5d1aff 100644
--- a/compiler/compiler.h
+++ b/compiler/compiler.h
@@ -22,16 +22,13 @@
 
 namespace art {
 
+class ArtMethod;
 class Backend;
 struct CompilationUnit;
 class CompilerDriver;
 class CompiledMethod;
 class OatWriter;
 
-namespace mirror {
-  class ArtMethod;
-}
-
 class Compiler {
  public:
   enum Kind {
@@ -60,7 +57,7 @@
                                      uint32_t method_idx,
                                      const DexFile& dex_file) const = 0;
 
-  virtual uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const
+  virtual uintptr_t GetEntryPointOf(ArtMethod* method) const
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
 
   uint64_t GetMaximumCompilationTimeBeforeWarning() const {
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index d1ddfda..bd59046 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -15,13 +15,13 @@
  */
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/mutex.h"
 #include "dex_file-inl.h"
 #include "dex_instruction-inl.h"
 #include "driver/compiler_driver.h"
 #include "driver/dex_compilation_unit.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
 #include "thread-inl.h"
diff --git a/compiler/dex/mir_method_info.cc b/compiler/dex/mir_method_info.cc
index 94be1fd..be913fe 100644
--- a/compiler/dex/mir_method_info.cc
+++ b/compiler/dex/mir_method_info.cc
@@ -83,7 +83,7 @@
     MethodReference devirt_ref(it->target_dex_file_, it->target_method_idx_);
     MethodReference* devirt_target = (it->target_dex_file_ != nullptr) ? &devirt_ref : nullptr;
     InvokeType invoke_type = it->GetInvokeType();
-    mirror::ArtMethod* resolved_method = nullptr;
+    ArtMethod* resolved_method = nullptr;
 
     bool string_init = false;
     if (default_inliner->IsStringInitMethodIndex(it->MethodIndex())) {
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 7679db8..7b1ec39 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -249,7 +249,7 @@
 size_t MIRGraph::GetNumBytesForSpecialTemps() const {
   // This logic is written with assumption that Method* is only special temp.
   DCHECK_EQ(max_available_special_compiler_temps_, 1u);
-  return sizeof(StackReference<mirror::ArtMethod>);
+  return InstructionSetPointerSize(cu_->instruction_set);
 }
 
 size_t MIRGraph::GetNumAvailableVRTemps() {
@@ -316,6 +316,7 @@
     // The vreg is always the first special temp for method ptr.
     compiler_temp->v_reg = GetFirstSpecialTempVR();
 
+    CHECK(reg_location_ == nullptr);
   } else if (ct_type == kCompilerTempBackend) {
     requested_backend_temp_ = true;
 
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index 822ea21..981ab2c 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -19,6 +19,7 @@
 #include "codegen_arm.h"
 
 #include "arm_lir.h"
+#include "art_method.h"
 #include "base/bit_utils.h"
 #include "base/logging.h"
 #include "dex/mir_graph.h"
@@ -27,7 +28,6 @@
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
 #include "gc/accounting/card_table.h"
-#include "mirror/art_method.h"
 #include "mirror/object_array-inl.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "utils/dex_cache_arrays_layout-inl.h"
@@ -637,7 +637,7 @@
       if (direct_code == 0) {
         // kInvokeTgt := arg0_ref->entrypoint
         cg->LoadWordDisp(arg0_ref,
-                         mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+                         ArtMethod::EntryPointFromQuickCompiledCodeOffset(
                              kArmPointerSize).Int32Value(), cg->TargetPtrReg(kInvokeTgt));
       }
       break;
@@ -678,7 +678,7 @@
     case 1:  // Get method->dex_cache_resolved_methods_
       if (!use_pc_rel) {
         cg->LoadRefDisp(arg0_ref,
-                        mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
+                        ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
                         arg0_ref,
                         kNotVolatile);
       }
@@ -708,14 +708,14 @@
                         kNotVolatile);
       } else {
         size_t offset = cg->dex_cache_arrays_layout_.MethodOffset(target_method.dex_method_index);
-        cg->OpPcRelDexCacheArrayLoad(cu->dex_file, offset, arg0_ref);
+        cg->OpPcRelDexCacheArrayLoad(cu->dex_file, offset, arg0_ref, false);
       }
       break;
     case 3:  // Grab the code from the method*
       if (direct_code == 0) {
         // kInvokeTgt := arg0_ref->entrypoint
         cg->LoadWordDisp(arg0_ref,
-                         mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+                         ArtMethod::EntryPointFromQuickCompiledCodeOffset(
                              kArmPointerSize).Int32Value(), cg->TargetPtrReg(kInvokeTgt));
       }
       break;
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 83b27df..b94e707 100644
--- a/compiler/dex/quick/arm/codegen_arm.h
+++ b/compiler/dex/quick/arm/codegen_arm.h
@@ -83,7 +83,8 @@
     void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE;
 
     bool CanUseOpPcRelDexCacheArrayLoad() const OVERRIDE;
-    void OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest) OVERRIDE;
+    void OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest,
+                                  bool wide) OVERRIDE;
 
     // Required for target - register utilities.
     RegStorage TargetReg(SpecialTargetRegister reg) OVERRIDE;
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc
index 7de8e55..6d30e72 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -1107,7 +1107,9 @@
   dex_cache_access_insns_.push_back(movt);
 }
 
-void ArmMir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest) {
+void ArmMir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest,
+                                          bool wide) {
+  DCHECK(!wide) << "Unsupported";
   if (dex_cache_arrays_base_reg_.Valid()) {
     LoadRefDisp(dex_cache_arrays_base_reg_, offset - dex_cache_arrays_min_offset_,
                 r_dest, kNotVolatile);
diff --git a/compiler/dex/quick/arm64/arm64_lir.h b/compiler/dex/quick/arm64/arm64_lir.h
index 303ea3e..2253d10 100644
--- a/compiler/dex/quick/arm64/arm64_lir.h
+++ b/compiler/dex/quick/arm64/arm64_lir.h
@@ -72,7 +72,7 @@
  * | IN[ins-1]                                  |  {Note: resides in caller's frame}
  * |       .                                    |
  * | IN[0]                                      |
- * | caller's method (StackReference<ArtMethod>)|  {This is a compressed (4-bytes) reference}
+ * | caller's method ArtMethod*                 |  {Pointer sized reference}
  * +============================================+  {Note: start of callee's frame}
  * | spill region                               |  {variable sized - will include lr if non-leaf}
  * +--------------------------------------------+
@@ -91,7 +91,7 @@
  * | OUT[outs-2]                                |
  * |       .                                    |
  * | OUT[0]                                     |
- * | current method (StackReference<ArtMethod>) | <<== sp w/ 16-byte alignment
+ * | current method ArtMethod*                  | <<== sp w/ 16-byte alignment
  * +============================================+
  */
 
diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc
index e49e40d..83a6aff 100644
--- a/compiler/dex/quick/arm64/call_arm64.cc
+++ b/compiler/dex/quick/arm64/call_arm64.cc
@@ -19,6 +19,7 @@
 #include "codegen_arm64.h"
 
 #include "arm64_lir.h"
+#include "art_method.h"
 #include "base/logging.h"
 #include "dex/mir_graph.h"
 #include "dex/quick/dex_file_to_method_inliner_map.h"
@@ -27,7 +28,6 @@
 #include "driver/compiler_options.h"
 #include "gc/accounting/card_table.h"
 #include "entrypoints/quick/quick_entrypoints.h"
-#include "mirror/art_method.h"
 #include "mirror/object_array-inl.h"
 #include "utils/dex_cache_arrays_layout-inl.h"
 
@@ -456,23 +456,22 @@
  */
 int Arm64Mir2Lir::Arm64NextSDCallInsn(CompilationUnit* cu, CallInfo* info,
                                       int state, const MethodReference& target_method,
-                                      uint32_t unused_idx,
+                                      uint32_t unused_idx ATTRIBUTE_UNUSED,
                                       uintptr_t direct_code, uintptr_t direct_method,
                                       InvokeType type) {
-  UNUSED(info, unused_idx);
   Arm64Mir2Lir* cg = static_cast<Arm64Mir2Lir*>(cu->cg.get());
   if (info->string_init_offset != 0) {
     RegStorage arg0_ref = cg->TargetReg(kArg0, kRef);
     switch (state) {
     case 0: {  // Grab target method* from thread pointer
-      cg->LoadRefDisp(rs_xSELF, info->string_init_offset, arg0_ref, kNotVolatile);
+      cg->LoadWordDisp(rs_xSELF, info->string_init_offset, arg0_ref);
       break;
     }
     case 1:  // Grab the code from the method*
       if (direct_code == 0) {
         // kInvokeTgt := arg0_ref->entrypoint
         cg->LoadWordDisp(arg0_ref,
-                         mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+                         ArtMethod::EntryPointFromQuickCompiledCodeOffset(
                              kArm64PointerSize).Int32Value(), cg->TargetPtrReg(kInvokeTgt));
       }
       break;
@@ -500,7 +499,7 @@
     }
   } else {
     bool use_pc_rel = cg->CanUseOpPcRelDexCacheArrayLoad();
-    RegStorage arg0_ref = cg->TargetReg(kArg0, kRef);
+    RegStorage arg0_ref = cg->TargetPtrReg(kArg0);
     switch (state) {
     case 0:  // Get the current Method* [sets kArg0]
       // TUNING: we can save a reg copy if Method* has been promoted.
@@ -513,7 +512,7 @@
     case 1:  // Get method->dex_cache_resolved_methods_
       if (!use_pc_rel) {
         cg->LoadRefDisp(arg0_ref,
-                        mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
+                        ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
                         arg0_ref,
                         kNotVolatile);
       }
@@ -536,21 +535,19 @@
     case 2:  // Grab target method*
       CHECK_EQ(cu->dex_file, target_method.dex_file);
       if (!use_pc_rel) {
-        cg->LoadRefDisp(arg0_ref,
-                        mirror::ObjectArray<mirror::Object>::OffsetOfElement(
-                            target_method.dex_method_index).Int32Value(),
-                        arg0_ref,
-                        kNotVolatile);
+        cg->LoadWordDisp(arg0_ref,
+                         mirror::Array::DataOffset(kArm64PointerSize).Uint32Value() +
+                         target_method.dex_method_index * kArm64PointerSize, arg0_ref);
       } else {
         size_t offset = cg->dex_cache_arrays_layout_.MethodOffset(target_method.dex_method_index);
-        cg->OpPcRelDexCacheArrayLoad(cu->dex_file, offset, arg0_ref);
+        cg->OpPcRelDexCacheArrayLoad(cu->dex_file, offset, arg0_ref, true);
       }
       break;
     case 3:  // Grab the code from the method*
       if (direct_code == 0) {
         // kInvokeTgt := arg0_ref->entrypoint
         cg->LoadWordDisp(arg0_ref,
-                         mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+                         ArtMethod::EntryPointFromQuickCompiledCodeOffset(
                              kArm64PointerSize).Int32Value(), cg->TargetPtrReg(kInvokeTgt));
       }
       break;
diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h
index 8184f02..ca2e012 100644
--- a/compiler/dex/quick/arm64/codegen_arm64.h
+++ b/compiler/dex/quick/arm64/codegen_arm64.h
@@ -79,7 +79,8 @@
   void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE;
 
   bool CanUseOpPcRelDexCacheArrayLoad() const OVERRIDE;
-  void OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest) OVERRIDE;
+  void OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest, bool wide)
+      OVERRIDE;
 
   LIR* OpCmpMemImmBranch(ConditionCode cond, RegStorage temp_reg, RegStorage base_reg,
                          int offset, int check_value, LIR* target, LIR** compare) OVERRIDE;
diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc
index 08aa5d2..31cf667 100644
--- a/compiler/dex/quick/arm64/int_arm64.cc
+++ b/compiler/dex/quick/arm64/int_arm64.cc
@@ -947,14 +947,17 @@
   return dex_cache_arrays_layout_.Valid();
 }
 
-void Arm64Mir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset,
-                                            RegStorage r_dest) {
+void Arm64Mir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest,
+                                            bool wide) {
   LIR* adrp = NewLIR2(kA64Adrp2xd, r_dest.GetReg(), 0);
   adrp->operands[2] = WrapPointer(dex_file);
   adrp->operands[3] = offset;
   adrp->operands[4] = WrapPointer(adrp);
   dex_cache_access_insns_.push_back(adrp);
-  LIR* ldr = LoadBaseDisp(r_dest, 0, r_dest, kReference, kNotVolatile);
+  if (wide) {
+    DCHECK(r_dest.Is64Bit());
+  }
+  LIR* ldr = LoadBaseDisp(r_dest, 0, r_dest, wide ? k64 : kReference, kNotVolatile);
   ldr->operands[4] = adrp->operands[4];
   ldr->flags.fixup = kFixupLabel;
   dex_cache_access_insns_.push_back(ldr);
diff --git a/compiler/dex/quick/arm64/target_arm64.cc b/compiler/dex/quick/arm64/target_arm64.cc
index fe15391..6efa11e 100644
--- a/compiler/dex/quick/arm64/target_arm64.cc
+++ b/compiler/dex/quick/arm64/target_arm64.cc
@@ -858,7 +858,8 @@
 
   // PC-relative references to dex cache arrays.
   for (LIR* p : dex_cache_access_insns_) {
-    DCHECK(p->opcode == kA64Adrp2xd || p->opcode == kA64Ldr3rXD);
+    auto non_wide = UNWIDE(p->opcode);  // May be a wide load for ArtMethod*.
+    DCHECK(non_wide == kA64Adrp2xd || non_wide == kA64Ldr3rXD) << p->opcode << " " << non_wide;
     const LIR* adrp = UnwrapPointer<LIR>(p->operands[4]);
     DCHECK_EQ(adrp->opcode, kA64Adrp2xd);
     const DexFile* dex_file = UnwrapPointer<DexFile>(adrp->operands[2]);
@@ -894,8 +895,7 @@
       rl_src[0] = mir_graph_->GetSrc(mir, 0);
       rl_src[1] = mir_graph_->GetSrc(mir, 1);
       rl_src[2]= mir_graph_->GetSrc(mir, 2);
-      GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2],
-                     (opcode == kMirOpMsubInt) ? true : false);
+      GenMaddMsubInt(rl_dest, rl_src[0], rl_src[1], rl_src[2], opcode == kMirOpMsubInt);
       break;
     case kMirOpMaddLong:
     case kMirOpMsubLong:
@@ -903,8 +903,7 @@
       rl_src[0] = mir_graph_->GetSrcWide(mir, 0);
       rl_src[1] = mir_graph_->GetSrcWide(mir, 2);
       rl_src[2] = mir_graph_->GetSrcWide(mir, 4);
-      GenMaddMsubLong(rl_dest, rl_src[0], rl_src[1], rl_src[2],
-                      (opcode == kMirOpMsubLong) ? true : false);
+      GenMaddMsubLong(rl_dest, rl_src[0], rl_src[1], rl_src[2], opcode == kMirOpMsubLong);
       break;
     default:
       LOG(FATAL) << "Unexpected opcode: " << static_cast<int>(opcode);
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index dc8bf1a..c803e65 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -1298,8 +1298,8 @@
     // resolve these invokes to the same method, so we don't care which one we record here.
     data_target->operands[2] = type;
   }
-  // Loads an ArtMethod pointer, which is a reference as it lives in the heap.
-  OpPcRelLoad(TargetReg(symbolic_reg, kRef), data_target);
+  // Loads an ArtMethod pointer, which is not a reference.
+  OpPcRelLoad(TargetPtrReg(symbolic_reg), data_target);
   DCHECK_NE(cu_->instruction_set, kMips) << reinterpret_cast<void*>(data_target);
   DCHECK_NE(cu_->instruction_set, kMips64) << reinterpret_cast<void*>(data_target);
 }
@@ -1322,7 +1322,8 @@
 
 void Mir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file ATTRIBUTE_UNUSED,
                                        int offset ATTRIBUTE_UNUSED,
-                                       RegStorage r_dest ATTRIBUTE_UNUSED) {
+                                       RegStorage r_dest ATTRIBUTE_UNUSED,
+                                       bool wide ATTRIBUTE_UNUSED) {
   LOG(FATAL) << "No generic implementation.";
   UNREACHABLE();
 }
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index 63f83f9..af10817 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -97,11 +97,11 @@
   LockTemp(r_base);
   if (CanUseOpPcRelDexCacheArrayLoad()) {
     uint32_t offset = dex_cache_arrays_layout_.TypeOffset(field_info.StorageIndex());
-    OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, r_base);
+    OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, r_base, false);
   } else {
     // Using fixed register to sync with possible call to runtime support.
     RegStorage r_method = LoadCurrMethodWithHint(r_base);
-    LoadRefDisp(r_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base,
+    LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base,
                 kNotVolatile);
     int32_t offset_of_field = ObjArray::OffsetOfElement(field_info.StorageIndex()).Int32Value();
     LoadRefDisp(r_base, offset_of_field, r_base, kNotVolatile);
@@ -693,7 +693,7 @@
       // Fast path, static storage base is this method's class
       r_base = AllocTempRef();
       RegStorage r_method = LoadCurrMethodWithHint(r_base);
-      LoadRefDisp(r_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base,
+      LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(), r_base,
                   kNotVolatile);
     } else {
       // Medium path, static storage base in a different class which requires checks that the other
@@ -771,7 +771,7 @@
       // Fast path, static storage base is this method's class
       r_base = AllocTempRef();
       RegStorage r_method = LoadCurrMethodWithHint(r_base);
-      LoadRefDisp(r_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base,
+      LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(), r_base,
                   kNotVolatile);
     } else {
       // Medium path, static storage base in a different class which requires checks that the other
@@ -1031,10 +1031,10 @@
     // We don't need access checks, load type from dex cache
     if (CanUseOpPcRelDexCacheArrayLoad()) {
       size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
-      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, rl_result.reg);
+      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, rl_result.reg, false);
     } else {
       int32_t dex_cache_offset =
-          mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value();
+          ArtMethod::DexCacheResolvedTypesOffset().Int32Value();
       RegStorage res_reg = AllocTempRef();
       RegStorage r_method = LoadCurrMethodWithHint(res_reg);
       LoadRefDisp(r_method, dex_cache_offset, res_reg, kNotVolatile);
@@ -1066,13 +1066,12 @@
     RegStorage ret0 = TargetReg(kRet0, kRef);
     if (CanUseOpPcRelDexCacheArrayLoad()) {
       size_t offset = dex_cache_arrays_layout_.StringOffset(string_idx);
-      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, ret0);
+      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, ret0, false);
     } else {
       // Method to declaring class.
       RegStorage arg0 = TargetReg(kArg0, kRef);
       RegStorage r_method = LoadCurrMethodWithHint(arg0);
-      LoadRefDisp(r_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
-                  arg0, kNotVolatile);
+      LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(), arg0, kNotVolatile);
       // Declaring class to dex cache strings.
       LoadRefDisp(arg0, mirror::Class::DexCacheStringsOffset().Int32Value(), arg0, kNotVolatile);
 
@@ -1086,11 +1085,11 @@
     RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
     if (CanUseOpPcRelDexCacheArrayLoad()) {
       size_t offset = dex_cache_arrays_layout_.StringOffset(string_idx);
-      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, rl_result.reg);
+      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, rl_result.reg, false);
     } else {
       RegLocation rl_method = LoadCurrMethod();
       RegStorage res_reg = AllocTempRef();
-      LoadRefDisp(rl_method.reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(), res_reg,
+      LoadRefDisp(rl_method.reg, ArtMethod::DeclaringClassOffset().Int32Value(), res_reg,
                   kNotVolatile);
       LoadRefDisp(res_reg, mirror::Class::DexCacheStringsOffset().Int32Value(), res_reg,
                   kNotVolatile);
@@ -1173,18 +1172,18 @@
 
   if (use_declaring_class) {
     RegStorage r_method = LoadCurrMethodWithHint(check_class);
-    LoadRefDisp(r_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value(), check_class,
+    LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(), check_class,
                 kNotVolatile);
     LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
                 kNotVolatile);
   } else if (CanUseOpPcRelDexCacheArrayLoad()) {
     size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
-    OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, check_class);
+    OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, check_class, false);
     LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
                 kNotVolatile);
   } else {
     RegStorage r_method = LoadCurrMethodWithHint(check_class);
-    LoadRefDisp(r_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+    LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                 check_class, kNotVolatile);
     LoadRefDisp(object.reg,  mirror::Object::ClassOffset().Int32Value(), object_class,
                 kNotVolatile);
@@ -1232,7 +1231,7 @@
   } else if (use_declaring_class) {
     RegStorage r_method = LoadCurrMethodWithHint(TargetReg(kArg1, kRef));
     LoadValueDirectFixed(rl_src, ref_reg);  // kArg0 <= ref
-    LoadRefDisp(r_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+    LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(),
                 class_reg, kNotVolatile);
   } else {
     if (can_assume_type_is_in_dex_cache) {
@@ -1242,11 +1241,11 @@
 
     if (CanUseOpPcRelDexCacheArrayLoad()) {
       size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
-      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg);
+      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg, false);
     } else {
       RegStorage r_method = LoadCurrMethodWithHint(class_reg);
       // Load dex cache entry into class_reg (kArg2)
-      LoadRefDisp(r_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+      LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                   class_reg, kNotVolatile);
       int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
       LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
@@ -1367,17 +1366,17 @@
     OpRegCopy(class_reg, TargetReg(kRet0, kRef));  // Align usage with fast path
   } else if (use_declaring_class) {
     RegStorage method_reg = LoadCurrMethodWithHint(TargetReg(kArg1, kRef));
-    LoadRefDisp(method_reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+    LoadRefDisp(method_reg, ArtMethod::DeclaringClassOffset().Int32Value(),
                 class_reg, kNotVolatile);
   } else {
     // Load dex cache entry into class_reg (kArg2)
     if (CanUseOpPcRelDexCacheArrayLoad()) {
       size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
-      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg);
+      OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg, false);
     } else {
       RegStorage r_method = LoadCurrMethodWithHint(class_reg);
 
-      LoadRefDisp(r_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+      LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                   class_reg, kNotVolatile);
       int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
       LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index ab011fc..1f114cf 100755
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -398,7 +398,7 @@
 // TODO: Support 64-bit argument registers.
 void Mir2Lir::FlushIns(RegLocation* ArgLocs, RegLocation rl_method) {
   /*
-   * Dummy up a RegLocation for the incoming StackReference<mirror::ArtMethod>
+   * Dummy up a RegLocation for the incoming ArtMethod*
    * It will attempt to keep kArg0 live (or copy it to home location
    * if promoted).
    */
@@ -407,10 +407,15 @@
   rl_src.reg = TargetReg(kArg0, kRef);
   rl_src.home = false;
   MarkLive(rl_src);
-  StoreValue(rl_method, rl_src);
+  if (cu_->target64) {
+    DCHECK(rl_method.wide);
+    StoreValueWide(rl_method, rl_src);
+  } else {
+    StoreValue(rl_method, rl_src);
+  }
   // If Method* has been promoted, explicitly flush
   if (rl_method.location == kLocPhysReg) {
-    StoreRefDisp(TargetPtrReg(kSp), 0, rl_src.reg, kNotVolatile);
+    StoreBaseDisp(TargetPtrReg(kSp), 0, rl_src.reg, kWord, kNotVolatile);
   }
 
   if (mir_graph_->GetNumOfInVRs() == 0) {
@@ -498,7 +503,7 @@
 static bool CommonCallCodeLoadCodePointerIntoInvokeTgt(const RegStorage* alt_from,
                                                        const CompilationUnit* cu, Mir2Lir* cg) {
   if (cu->instruction_set != kX86 && cu->instruction_set != kX86_64) {
-    int32_t offset = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+    int32_t offset = ArtMethod::EntryPointFromQuickCompiledCodeOffset(
         InstructionSetPointerSize(cu->instruction_set)).Int32Value();
     // Get the compiled code address [use *alt_from or kArg0, set kInvokeTgt]
     cg->LoadWordDisp(alt_from == nullptr ? cg->TargetReg(kArg0, kRef) : *alt_from, offset,
@@ -535,10 +540,12 @@
       break;
     case 2: {
       // Get this->klass_.embedded_vtable[method_idx] [usr kArg0, set kArg0]
-      int32_t offset = mirror::Class::EmbeddedVTableOffset().Uint32Value() +
-          method_idx * sizeof(mirror::Class::VTableEntry);
+      const size_t pointer_size = InstructionSetPointerSize(
+          cu->compiler_driver->GetInstructionSet());
+      int32_t offset = mirror::Class::EmbeddedVTableEntryOffset(
+          method_idx, pointer_size).Uint32Value();
       // Load target method from embedded vtable to kArg0 [use kArg0, set kArg0]
-      cg->LoadRefDisp(cg->TargetReg(kArg0, kRef), offset, cg->TargetReg(kArg0, kRef), kNotVolatile);
+      cg->LoadWordDisp(cg->TargetPtrReg(kArg0), offset, cg->TargetPtrReg(kArg0));
       break;
     }
     case 3:
@@ -580,10 +587,12 @@
                                                   // Includes a null-check.
       break;
     case 3: {  // Get target method [use kInvokeTgt, set kArg0]
-      int32_t offset = mirror::Class::EmbeddedImTableOffset().Uint32Value() +
-          (method_idx % mirror::Class::kImtSize) * sizeof(mirror::Class::ImTableEntry);
+      const size_t pointer_size = InstructionSetPointerSize(
+          cu->compiler_driver->GetInstructionSet());
+      int32_t offset = mirror::Class::EmbeddedImTableEntryOffset(
+          method_idx % mirror::Class::kImtSize, pointer_size).Uint32Value();
       // Load target method from embedded imtable to kArg0 [use kArg0, set kArg0]
-      cg->LoadRefDisp(cg->TargetReg(kArg0, kRef), offset, cg->TargetReg(kArg0, kRef), kNotVolatile);
+      cg->LoadWordDisp(cg->TargetPtrReg(kArg0), offset, cg->TargetPtrReg(kArg0));
       break;
     }
     case 4:
@@ -967,7 +976,7 @@
   RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
   GenNullCheck(rl_obj.reg, info->opt_flags);
   LoadRefDisp(rl_obj.reg, mirror::Reference::ReferentOffset().Int32Value(), rl_result.reg,
-      kNotVolatile);
+              kNotVolatile);
   MarkPossibleNullPointerException(info->opt_flags);
   StoreValue(rl_dest, rl_result);
 
@@ -1418,7 +1427,7 @@
 
   RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true);
 
-  if (Is64BitInstructionSet(cu_->instruction_set)) {
+  if (cu_->target64) {
     LoadRefDisp(TargetPtrReg(kSelf), Thread::PeerOffset<8>().Int32Value(), rl_result.reg,
                 kNotVolatile);
   } else {
diff --git a/compiler/dex/quick/gen_loadstore.cc b/compiler/dex/quick/gen_loadstore.cc
index 4215e8b..aa95e77 100644
--- a/compiler/dex/quick/gen_loadstore.cc
+++ b/compiler/dex/quick/gen_loadstore.cc
@@ -42,7 +42,7 @@
  * register liveness.  That is the responsibility of the caller.
  */
 void Mir2Lir::LoadValueDirect(RegLocation rl_src, RegStorage r_dest) {
-  rl_src = UpdateLoc(rl_src);
+  rl_src = rl_src.wide ? UpdateLocWide(rl_src) : UpdateLoc(rl_src);
   if (rl_src.location == kLocPhysReg) {
     OpRegCopy(r_dest, rl_src.reg);
   } else if (IsInexpensiveConstant(rl_src)) {
@@ -53,11 +53,15 @@
     DCHECK((rl_src.location == kLocDalvikFrame) ||
            (rl_src.location == kLocCompilerTemp));
     ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg);
+    OpSize op_size;
     if (rl_src.ref) {
-      LoadRefDisp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, kNotVolatile);
+      op_size = kReference;
+    } else if (rl_src.wide) {
+      op_size = k64;
     } else {
-      Load32Disp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest);
+      op_size = k32;
     }
+    LoadBaseDisp(TargetPtrReg(kSp), SRegOffset(rl_src.s_reg_low), r_dest, op_size, kNotVolatile);
   }
 }
 
@@ -337,7 +341,11 @@
 
 /* Utilities to load the current Method* */
 void Mir2Lir::LoadCurrMethodDirect(RegStorage r_tgt) {
-  LoadValueDirectFixed(mir_graph_->GetMethodLoc(), r_tgt);
+  if (GetCompilationUnit()->target64) {
+    LoadValueDirectWideFixed(mir_graph_->GetMethodLoc(), r_tgt);
+  } else {
+    LoadValueDirectFixed(mir_graph_->GetMethodLoc(), r_tgt);
+  }
 }
 
 RegStorage Mir2Lir::LoadCurrMethodWithHint(RegStorage r_hint) {
@@ -355,7 +363,9 @@
 }
 
 RegLocation Mir2Lir::LoadCurrMethod() {
-  return LoadValue(mir_graph_->GetMethodLoc(), kRefReg);
+  return GetCompilationUnit()->target64 ?
+      LoadValueWide(mir_graph_->GetMethodLoc(), kCoreReg) :
+      LoadValue(mir_graph_->GetMethodLoc(), kRefReg);
 }
 
 RegLocation Mir2Lir::ForceTemp(RegLocation loc) {
diff --git a/compiler/dex/quick/mips/call_mips.cc b/compiler/dex/quick/mips/call_mips.cc
index 3d25384..da12d8e 100644
--- a/compiler/dex/quick/mips/call_mips.cc
+++ b/compiler/dex/quick/mips/call_mips.cc
@@ -18,6 +18,7 @@
 
 #include "codegen_mips.h"
 
+#include "art_method.h"
 #include "base/logging.h"
 #include "dex/mir_graph.h"
 #include "dex/quick/dex_file_to_method_inliner_map.h"
@@ -26,7 +27,6 @@
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "gc/accounting/card_table.h"
 #include "mips_lir.h"
-#include "mirror/art_method.h"
 #include "mirror/object_array-inl.h"
 
 namespace art {
@@ -407,12 +407,12 @@
     RegStorage arg0_ref = cg->TargetReg(kArg0, kRef);
     switch (state) {
     case 0: {  // Grab target method* from thread pointer
-      cg->LoadRefDisp(cg->TargetPtrReg(kSelf), info->string_init_offset, arg0_ref, kNotVolatile);
+      cg->LoadWordDisp(cg->TargetPtrReg(kSelf), info->string_init_offset, arg0_ref);
       break;
     }
     case 1:  // Grab the code from the method*
       if (direct_code == 0) {
-        int32_t offset = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+        int32_t offset = ArtMethod::EntryPointFromQuickCompiledCodeOffset(
             InstructionSetPointerSize(cu->instruction_set)).Int32Value();
         cg->LoadWordDisp(arg0_ref, offset, cg->TargetPtrReg(kInvokeTgt));
       }
@@ -454,7 +454,7 @@
         break;
       case 1:  // Get method->dex_cache_resolved_methods_
         cg->LoadRefDisp(arg0_ref,
-                        mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
+                        ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
                         arg0_ref,
                         kNotVolatile);
         // Set up direct code if known.
@@ -471,17 +471,18 @@
           }
         }
         break;
-      case 2:  // Grab target method*
+      case 2: {
+        // Grab target method*
         CHECK_EQ(cu->dex_file, target_method.dex_file);
-        cg->LoadRefDisp(arg0_ref,
-                        mirror::ObjectArray<mirror::Object>::
-                        OffsetOfElement(target_method.dex_method_index).Int32Value(),
-                        arg0_ref,
-                        kNotVolatile);
+        const size_t pointer_size = GetInstructionSetPointerSize(cu->instruction_set);
+        cg->LoadWordDisp(arg0_ref,
+                         mirror::Array::DataOffset(pointer_size).Uint32Value() +
+                         target_method.dex_method_index * pointer_size, arg0_ref);
         break;
+      }
       case 3:  // Grab the code from the method*
         if (direct_code == 0) {
-          int32_t offset = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+          int32_t offset = ArtMethod::EntryPointFromQuickCompiledCodeOffset(
               InstructionSetPointerSize(cu->instruction_set)).Int32Value();
           // Get the compiled code address [use *alt_from or kArg0, set kInvokeTgt]
           cg->LoadWordDisp(arg0_ref, offset, cg->TargetPtrReg(kInvokeTgt));
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index e3e87ec..7ca03cf 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -1232,6 +1232,10 @@
     ResetRegPool();
     int start_vreg = mir_graph_->GetFirstInVR();
     AppendLIR(NewLIR0(kPseudoPrologueBegin));
+    DCHECK_EQ(cu_->target64, Is64BitInstructionSet(cu_->instruction_set));
+    if (cu_->target64) {
+      DCHECK(mir_graph_->GetMethodLoc().wide);
+    }
     GenEntrySequence(&mir_graph_->reg_location_[start_vreg], mir_graph_->GetMethodLoc());
     AppendLIR(NewLIR0(kPseudoPrologueEnd));
     DCHECK_EQ(cfi_.GetCurrentCFAOffset(), frame_size_);
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index d54616f..73787e9 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -982,12 +982,11 @@
     }
     // Load a reference at base + displacement and decompress into register.
     LIR* LoadRefDisp(RegStorage r_base, int displacement, RegStorage r_dest,
-                             VolatileKind is_volatile) {
+                     VolatileKind is_volatile) {
       return LoadBaseDisp(r_base, displacement, r_dest, kReference, is_volatile);
     }
     // Load a reference at base + index and decompress into register.
-    LIR* LoadRefIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
-                                int scale) {
+    LIR* LoadRefIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, int scale) {
       return LoadBaseIndexed(r_base, r_index, r_dest, scale, kReference);
     }
     // Load Dalvik value with 32-bit memory storage.  If compressed object reference, decompress.
@@ -1008,12 +1007,11 @@
     }
     // Store an uncompressed reference into a compressed 32-bit container.
     LIR* StoreRefDisp(RegStorage r_base, int displacement, RegStorage r_src,
-                              VolatileKind is_volatile) {
+                      VolatileKind is_volatile) {
       return StoreBaseDisp(r_base, displacement, r_src, kReference, is_volatile);
     }
     // Store an uncompressed reference into a compressed 32-bit container by index.
-    LIR* StoreRefIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
-                                 int scale) {
+    LIR* StoreRefIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, int scale) {
       return StoreBaseIndexed(r_base, r_index, r_src, scale, kReference);
     }
     // Store 32 bits, regardless of target.
@@ -1117,8 +1115,10 @@
      * @param dex_file the dex file associated with the target dex cache.
      * @param offset the offset of the element in the fixed dex cache arrays' layout.
      * @param r_dest the register where to load the element.
+     * @param wide, load 64 bits if true, otherwise 32 bits.
      */
-    virtual void OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest);
+    virtual void OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest,
+                                          bool wide);
 
     // Routines that work for the generic case, but may be overriden by target.
     /*
diff --git a/compiler/dex/quick/quick_cfi_test.cc b/compiler/dex/quick/quick_cfi_test.cc
index 87bbe14..dd68dd4 100644
--- a/compiler/dex/quick/quick_cfi_test.cc
+++ b/compiler/dex/quick/quick_cfi_test.cc
@@ -99,7 +99,8 @@
       }
     }
     m2l->AdjustSpillMask();
-    m2l->GenEntrySequence(nullptr, m2l->LocCReturnRef());
+    m2l->GenEntrySequence(nullptr, m2l->GetCompilationUnit()->target64 ?
+        m2l->LocCReturnWide() : m2l->LocCReturnRef());
     m2l->GenExitSequence();
     m2l->HandleSlowPaths();
     m2l->AssembleLIR();
diff --git a/compiler/dex/quick/quick_cfi_test_expected.inc b/compiler/dex/quick/quick_cfi_test_expected.inc
index 634fdee..3032697 100644
--- a/compiler/dex/quick/quick_cfi_test_expected.inc
+++ b/compiler/dex/quick/quick_cfi_test_expected.inc
@@ -34,7 +34,7 @@
 
 static constexpr uint8_t expected_asm_kArm64[] = {
     0xFF, 0x03, 0x01, 0xD1, 0xE8, 0xA7, 0x01, 0x6D, 0xF4, 0xD7, 0x02, 0xA9,
-    0xFE, 0x1F, 0x00, 0xF9, 0xE0, 0x03, 0x00, 0xB9, 0xE8, 0xA7, 0x41, 0x6D,
+    0xFE, 0x1F, 0x00, 0xF9, 0xE0, 0x03, 0x00, 0xF9, 0xE8, 0xA7, 0x41, 0x6D,
     0xF4, 0xD7, 0x42, 0xA9, 0xFE, 0x1F, 0x40, 0xF9, 0xFF, 0x03, 0x01, 0x91,
     0xC0, 0x03, 0x5F, 0xD6,
 };
@@ -54,7 +54,7 @@
 // 0x0000000c: .cfi_offset: r21 at cfa-16
 // 0x0000000c: str lr, [sp, #56]
 // 0x00000010: .cfi_offset: r30 at cfa-8
-// 0x00000010: str w0, [sp]
+// 0x00000010: str x0, [sp]
 // 0x00000014: .cfi_remember_state
 // 0x00000014: ldp d8, d9, [sp, #24]
 // 0x00000018: .cfi_restore_extended: r72
@@ -101,15 +101,15 @@
 static constexpr uint8_t expected_asm_kX86_64[] = {
     0x48, 0x83, 0xEC, 0x38, 0x48, 0x89, 0x5C, 0x24, 0x28, 0x48, 0x89, 0x6C,
     0x24, 0x30, 0xF2, 0x44, 0x0F, 0x11, 0x64, 0x24, 0x18, 0xF2, 0x44, 0x0F,
-    0x11, 0x6C, 0x24, 0x20, 0x48, 0x8B, 0xC7, 0x89, 0x3C, 0x24, 0x48, 0x8B,
-    0x5C, 0x24, 0x28, 0x48, 0x8B, 0x6C, 0x24, 0x30, 0xF2, 0x44, 0x0F, 0x10,
-    0x64, 0x24, 0x18, 0xF2, 0x44, 0x0F, 0x10, 0x6C, 0x24, 0x20, 0x48, 0x83,
-    0xC4, 0x38, 0xC3, 0x00,
+    0x11, 0x6C, 0x24, 0x20, 0x48, 0x8B, 0xC7, 0x48, 0x89, 0x3C, 0x24, 0x48,
+    0x8B, 0x5C, 0x24, 0x28, 0x48, 0x8B, 0x6C, 0x24, 0x30, 0xF2, 0x44, 0x0F,
+    0x10, 0x64, 0x24, 0x18, 0xF2, 0x44, 0x0F, 0x10, 0x6C, 0x24, 0x20, 0x48,
+    0x83, 0xC4, 0x38, 0xC3,
 };
 static constexpr uint8_t expected_cfi_kX86_64[] = {
     0x44, 0x0E, 0x40, 0x45, 0x83, 0x06, 0x45, 0x86, 0x04, 0x47, 0x9D, 0x0A,
-    0x47, 0x9E, 0x08, 0x46, 0x0A, 0x45, 0xC3, 0x45, 0xC6, 0x47, 0xDD, 0x47,
-    0xDE, 0x44, 0x0E, 0x08, 0x42, 0x0B, 0x0E, 0x40,
+    0x47, 0x9E, 0x08, 0x47, 0x0A, 0x45, 0xC3, 0x45, 0xC6, 0x47, 0xDD, 0x47,
+    0xDE, 0x44, 0x0E, 0x08, 0x41, 0x0B, 0x0E, 0x40,
 };
 // 0x00000000: subq rsp, 56
 // 0x00000004: .cfi_def_cfa_offset: 64
@@ -122,20 +122,19 @@
 // 0x00000015: movsd [rsp + 32], xmm13
 // 0x0000001c: .cfi_offset: r30 at cfa-32
 // 0x0000001c: movq rax, rdi
-// 0x0000001f: mov [rsp], edi
-// 0x00000022: .cfi_remember_state
-// 0x00000022: movq rbx, [rsp + 40]
-// 0x00000027: .cfi_restore: r3
-// 0x00000027: movq rbp, [rsp + 48]
-// 0x0000002c: .cfi_restore: r6
-// 0x0000002c: movsd xmm12, [rsp + 24]
-// 0x00000033: .cfi_restore: r29
-// 0x00000033: movsd xmm13, [rsp + 32]
-// 0x0000003a: .cfi_restore: r30
-// 0x0000003a: addq rsp, 56
-// 0x0000003e: .cfi_def_cfa_offset: 8
-// 0x0000003e: ret
-// 0x0000003f: addb al, al
+// 0x0000001f: movq [rsp], rdi
+// 0x00000023: .cfi_remember_state
+// 0x00000023: movq rbx, [rsp + 40]
+// 0x00000028: .cfi_restore: r3
+// 0x00000028: movq rbp, [rsp + 48]
+// 0x0000002d: .cfi_restore: r6
+// 0x0000002d: movsd xmm12, [rsp + 24]
+// 0x00000034: .cfi_restore: r29
+// 0x00000034: movsd xmm13, [rsp + 32]
+// 0x0000003b: .cfi_restore: r30
+// 0x0000003b: addq rsp, 56
+// 0x0000003f: .cfi_def_cfa_offset: 8
+// 0x0000003f: ret
 // 0x00000040: .cfi_restore_state
 // 0x00000040: .cfi_def_cfa_offset: 64
 
@@ -172,7 +171,7 @@
 // 0x00000028: .cfi_restore: r31
 // 0x00000028: addiu r29, r29, 64
 // 0x0000002c: .cfi_def_cfa_offset: 0
-// 0x0000002c: jalr r0, r31
+// 0x0000002c: jr r31
 // 0x00000030: nop
 // 0x00000034: .cfi_restore_state
 // 0x00000034: .cfi_def_cfa_offset: 64
@@ -180,7 +179,7 @@
 static constexpr uint8_t expected_asm_kMips64[] = {
     0xE8, 0xFF, 0xBD, 0x67, 0x10, 0x00, 0xB2, 0xFF, 0x08, 0x00, 0xB3, 0xFF,
     0x00, 0x00, 0xBF, 0xFF, 0xD8, 0xFF, 0xBD, 0x67, 0x25, 0x10, 0x80, 0x00,
-    0x00, 0x00, 0xA4, 0xAF, 0x38, 0x00, 0xB2, 0xDF, 0x30, 0x00, 0xB3, 0xDF,
+    0x00, 0x00, 0xA4, 0xFF, 0x38, 0x00, 0xB2, 0xDF, 0x30, 0x00, 0xB3, 0xDF,
     0x28, 0x00, 0xBF, 0xDF, 0x40, 0x00, 0xBD, 0x67, 0x09, 0x00, 0xE0, 0x03,
     0x00, 0x00, 0x00, 0x00,
 };
@@ -200,7 +199,7 @@
 // 0x00000010: daddiu r29, r29, -40
 // 0x00000014: .cfi_def_cfa_offset: 64
 // 0x00000014: or r2, r4, r0
-// 0x00000018: sw r4, +0(r29)
+// 0x00000018: sd r4, +0(r29)
 // 0x0000001c: .cfi_remember_state
 // 0x0000001c: ld r18, +56(r29)
 // 0x00000020: .cfi_restore: r18
@@ -214,4 +213,3 @@
 // 0x00000030: nop
 // 0x00000034: .cfi_restore_state
 // 0x00000034: .cfi_def_cfa_offset: 64
-
diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc
index 7ca4382..58236e2 100644
--- a/compiler/dex/quick/quick_compiler.cc
+++ b/compiler/dex/quick/quick_compiler.cc
@@ -18,6 +18,7 @@
 
 #include <cstdint>
 
+#include "art_method-inl.h"
 #include "base/dumpable.h"
 #include "base/logging.h"
 #include "base/macros.h"
@@ -37,7 +38,6 @@
 #include "elf_writer_quick.h"
 #include "jni/quick/jni_compiler.h"
 #include "mir_to_lir.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/object.h"
 #include "runtime.h"
 
@@ -787,7 +787,7 @@
   return ArtQuickJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file);
 }
 
-uintptr_t QuickCompiler::GetEntryPointOf(mirror::ArtMethod* method) const {
+uintptr_t QuickCompiler::GetEntryPointOf(ArtMethod* method) const {
   return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCodePtrSize(
       InstructionSetPointerSize(GetCompilerDriver()->GetInstructionSet())));
 }
diff --git a/compiler/dex/quick/quick_compiler.h b/compiler/dex/quick/quick_compiler.h
index 8d2c324..43dd578 100644
--- a/compiler/dex/quick/quick_compiler.h
+++ b/compiler/dex/quick/quick_compiler.h
@@ -49,7 +49,7 @@
                              uint32_t method_idx,
                              const DexFile& dex_file) const OVERRIDE;
 
-  uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const OVERRIDE
+  uintptr_t GetEntryPointOf(ArtMethod* method) const OVERRIDE
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static Mir2Lir* GetCodeGenerator(CompilationUnit* cu, void* compilation_unit);
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index 2495757..43167a1 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -18,13 +18,13 @@
 
 #include "codegen_x86.h"
 
+#include "art_method.h"
 #include "base/logging.h"
 #include "dex/quick/dex_file_to_method_inliner_map.h"
 #include "dex/quick/mir_to_lir-inl.h"
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
 #include "gc/accounting/card_table.h"
-#include "mirror/art_method.h"
 #include "mirror/object_array-inl.h"
 #include "utils/dex_cache_arrays_layout-inl.h"
 #include "x86_lir.h"
@@ -379,7 +379,8 @@
       case 0: {
         CHECK_EQ(cu->dex_file, target_method.dex_file);
         size_t offset = cg->dex_cache_arrays_layout_.MethodOffset(target_method.dex_method_index);
-        cg->OpPcRelDexCacheArrayLoad(cu->dex_file, offset, cg->TargetReg(kArg0, kRef));
+        cg->OpPcRelDexCacheArrayLoad(cu->dex_file, offset, cg->TargetReg(kArg0, kRef),
+                                     cu->target64);
         break;
       }
       default:
@@ -394,18 +395,20 @@
       break;
     case 1:  // Get method->dex_cache_resolved_methods_
       cg->LoadRefDisp(arg0_ref,
-                      mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
+                      ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
                       arg0_ref,
                       kNotVolatile);
       break;
-    case 2:  // Grab target method*
+    case 2: {
+      // Grab target method*
       CHECK_EQ(cu->dex_file, target_method.dex_file);
-      cg->LoadRefDisp(arg0_ref,
-                      mirror::ObjectArray<mirror::Object>::OffsetOfElement(
-                          target_method.dex_method_index).Int32Value(),
-                      arg0_ref,
-                      kNotVolatile);
+      const size_t pointer_size = GetInstructionSetPointerSize(cu->instruction_set);
+      cg->LoadWordDisp(arg0_ref,
+                       mirror::Array::DataOffset(pointer_size).Uint32Value() +
+                       target_method.dex_method_index * pointer_size,
+                       arg0_ref);
       break;
+    }
     default:
       return -1;
     }
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 5a46520..11d9d4a 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -105,7 +105,8 @@
   void UnconditionallyMarkGCCard(RegStorage tgt_addr_reg) OVERRIDE;
 
   bool CanUseOpPcRelDexCacheArrayLoad() const OVERRIDE;
-  void OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest) OVERRIDE;
+  void OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest, bool wide)
+      OVERRIDE;
 
   void GenImplicitNullCheck(RegStorage reg, int opt_flags) OVERRIDE;
 
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index 9bbb5f8..d993d93 100755
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -18,11 +18,11 @@
 
 #include "codegen_x86.h"
 
+#include "art_method.h"
 #include "base/bit_utils.h"
 #include "base/logging.h"
 #include "dex/quick/mir_to_lir-inl.h"
 #include "dex/reg_storage_eq.h"
-#include "mirror/art_method.h"
 #include "mirror/array-inl.h"
 #include "x86_lir.h"
 
@@ -1410,16 +1410,18 @@
   }
 }
 
-void X86Mir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset,
-                                          RegStorage r_dest) {
+void X86Mir2Lir::OpPcRelDexCacheArrayLoad(const DexFile* dex_file, int offset, RegStorage r_dest,
+                                          bool wide) {
   if (cu_->target64) {
-    LIR* mov = NewLIR3(kX86Mov32RM, r_dest.GetReg(), kRIPReg, kDummy32BitOffset);
+    LIR* mov = NewLIR3(wide ? kX86Mov64RM : kX86Mov32RM, r_dest.GetReg(), kRIPReg,
+        kDummy32BitOffset);
     mov->flags.fixup = kFixupLabel;
     mov->operands[3] = WrapPointer(dex_file);
     mov->operands[4] = offset;
     mov->target = mov;  // Used for pc_insn_offset (not used by x86-64 relative patcher).
     dex_cache_access_insns_.push_back(mov);
   } else {
+    CHECK(!wide) << "Unsupported";
     // Get the PC to a register and get the anchor. Use r_dest for the temp if needed.
     LIR* anchor;
     RegStorage r_pc = GetPcAndAnchor(&anchor, r_dest);
@@ -3022,20 +3024,20 @@
 
   if (rl_method.location == kLocPhysReg) {
     if (use_declaring_class) {
-      LoadRefDisp(rl_method.reg, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+      LoadRefDisp(rl_method.reg, ArtMethod::DeclaringClassOffset().Int32Value(),
                   check_class, kNotVolatile);
     } else {
-      LoadRefDisp(rl_method.reg, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+      LoadRefDisp(rl_method.reg, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                   check_class, kNotVolatile);
       LoadRefDisp(check_class, offset_of_type, check_class, kNotVolatile);
     }
   } else {
     LoadCurrMethodDirect(check_class);
     if (use_declaring_class) {
-      LoadRefDisp(check_class, mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
+      LoadRefDisp(check_class, ArtMethod::DeclaringClassOffset().Int32Value(),
                   check_class, kNotVolatile);
     } else {
-      LoadRefDisp(check_class, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+      LoadRefDisp(check_class, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
                   check_class, kNotVolatile);
       LoadRefDisp(check_class, offset_of_type, check_class, kNotVolatile);
     }
@@ -3059,7 +3061,7 @@
 }
 
 void X86Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest,
-                            RegLocation rl_lhs, RegLocation rl_rhs, int flags) {
+                               RegLocation rl_lhs, RegLocation rl_rhs, int flags) {
   OpKind op = kOpBkpt;
   bool is_div_rem = false;
   bool unary = false;
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 2f211da..c62cd47 100755
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -21,6 +21,7 @@
 #include <string>
 
 #include "arch/instruction_set_features.h"
+#include "art_method.h"
 #include "backend_x86.h"
 #include "base/logging.h"
 #include "dex/compiler_ir.h"
@@ -28,7 +29,6 @@
 #include "dex/reg_storage_eq.h"
 #include "driver/compiler_driver.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method.h"
 #include "mirror/string.h"
 #include "oat.h"
 #include "x86_lir.h"
@@ -744,6 +744,7 @@
   const RegStorage rs_rSP = cu_->target64 ? rs_rX86_SP_64 : rs_rX86_SP_32;
   for (int reg = 0; mask != 0u; mask >>= 1, reg++) {
     if ((mask & 0x1) != 0u) {
+      DCHECK_NE(offset, 0) << "offset 0 should be for method";
       RegStorage r_src = cu_->target64 ? RegStorage::Solo64(reg) : RegStorage::Solo32(reg);
       StoreBaseDisp(rs_rSP, offset, r_src, size, kNotVolatile);
       cfi_.RelOffset(DwarfCoreReg(cu_->target64, reg), offset);
@@ -1026,7 +1027,7 @@
       call_insn = CallWithLinkerFixup(method_info.GetTargetMethod(), method_info.GetSharpType());
     } else {
       call_insn = OpMem(kOpBlx, TargetReg(kArg0, kRef),
-                        mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+                        ArtMethod::EntryPointFromQuickCompiledCodeOffset(
                             cu_->target64 ? 8 : 4).Int32Value());
     }
   } else {
@@ -1103,7 +1104,7 @@
 
   // PC-relative references to dex cache arrays.
   for (LIR* p : dex_cache_access_insns_) {
-    DCHECK(p->opcode == kX86Mov32RM);
+    DCHECK(p->opcode == kX86Mov32RM || p->opcode == kX86Mov64RM);
     const DexFile* dex_file = UnwrapPointer<DexFile>(p->operands[3]);
     uint32_t offset = p->operands[4];
     // The offset to patch is the last 4 bytes of the instruction.
diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h
index 57db015..d6a6a60 100644
--- a/compiler/dex/quick/x86/x86_lir.h
+++ b/compiler/dex/quick/x86/x86_lir.h
@@ -82,7 +82,7 @@
  * | IN[ins-1]                 |  {Note: resides in caller's frame}
  * |       .                   |
  * | IN[0]                     |
- * | caller's Method*          |
+ * | caller's ArtMethod*       |
  * +===========================+  {Note: start of callee's frame}
  * | return address            |  {pushed by call}
  * | spill region              |  {variable sized}
@@ -104,7 +104,7 @@
  * | OUT[outs-2]               |
  * |       .                   |
  * | OUT[0]                    |
- * | StackReference<ArtMethod> | <<== sp w/ 16-byte alignment
+ * | ArtMethod*                | <<== sp w/ 16-byte alignment
  * +===========================+
  */
 
diff --git a/compiler/dex/type_inference.cc b/compiler/dex/type_inference.cc
index cd6467f..a0dfcbe 100644
--- a/compiler/dex/type_inference.cc
+++ b/compiler/dex/type_inference.cc
@@ -686,8 +686,8 @@
 void TypeInference::InitializeSRegs() {
   std::fill_n(sregs_, num_sregs_, Type::Unknown());
 
-  /* Treat ArtMethod* as a normal reference */
-  sregs_[mir_graph_->GetMethodSReg()] = Type::NonArrayRefType();
+  /* Treat ArtMethod* specially since they are pointer sized */
+  sregs_[mir_graph_->GetMethodSReg()] = Type::ArtMethodType(cu_->target64);
 
   // Initialize parameter SSA regs at method entry.
   int32_t entry_param_s_reg = mir_graph_->GetFirstInVR();
diff --git a/compiler/dex/type_inference.h b/compiler/dex/type_inference.h
index 85f79af..adc3b54 100644
--- a/compiler/dex/type_inference.h
+++ b/compiler/dex/type_inference.h
@@ -81,6 +81,10 @@
       return Type(kFlagLowWord | kFlagNarrow | kFlagRef);
     }
 
+    static Type ArtMethodType(bool wide) {
+      return Type(kFlagLowWord | kFlagRef | (wide ? kFlagWide : kFlagNarrow));
+    }
+
     static Type ObjectArrayType() {
       return Type(kFlagNarrow | kFlagRef | kFlagLowWord |
                   (1u << kBitArrayDepthStart) | kFlagArrayNarrow | kFlagArrayRef);
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index e788261..ac7a4a7 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -20,12 +20,12 @@
 #include <memory>
 #include <vector>
 
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "dex_file.h"
 #include "dex_instruction-inl.h"
 #include "dex_instruction_utils.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/object-inl.h"
@@ -212,7 +212,7 @@
     if (is_virtual_quick || is_range_quick) {
       uint32_t dex_pc = inst->GetDexPc(insns);
       verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
-      mirror::ArtMethod* method =
+      ArtMethod* method =
           method_verifier->GetQuickInvokedMethod(inst, line, is_range_quick, true);
       if (method == nullptr) {
         // It can be null if the line wasn't verified since it was unreachable.
@@ -284,20 +284,24 @@
       // We can't devirtualize abstract classes except on arrays of abstract classes.
       continue;
     }
-    mirror::ArtMethod* abstract_method = method_verifier->GetDexCache()->GetResolvedMethod(
-        is_range ? inst->VRegB_3rc() : inst->VRegB_35c());
+    auto* cl = Runtime::Current()->GetClassLinker();
+    size_t pointer_size = cl->GetImagePointerSize();
+    ArtMethod* abstract_method = method_verifier->GetDexCache()->GetResolvedMethod(
+        is_range ? inst->VRegB_3rc() : inst->VRegB_35c(), pointer_size);
     if (abstract_method == nullptr) {
       // If the method is not found in the cache this means that it was never found
       // by ResolveMethodAndCheckAccess() called when verifying invoke_*.
       continue;
     }
     // Find the concrete method.
-    mirror::ArtMethod* concrete_method = nullptr;
+    ArtMethod* concrete_method = nullptr;
     if (is_interface) {
-      concrete_method = reg_type.GetClass()->FindVirtualMethodForInterface(abstract_method);
+      concrete_method = reg_type.GetClass()->FindVirtualMethodForInterface(
+          abstract_method, pointer_size);
     }
     if (is_virtual) {
-      concrete_method = reg_type.GetClass()->FindVirtualMethodForVirtual(abstract_method);
+      concrete_method = reg_type.GetClass()->FindVirtualMethodForVirtual(
+          abstract_method, pointer_size);
     }
     if (concrete_method == nullptr || concrete_method->IsAbstract()) {
       // In cases where concrete_method is not found, or is abstract, continue to the next invoke.
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h
index e54cbf6..b25e967 100644
--- a/compiler/driver/compiler_driver-inl.h
+++ b/compiler/driver/compiler_driver-inl.h
@@ -20,8 +20,9 @@
 #include "compiler_driver.h"
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
+#include "class_linker-inl.h"
 #include "dex_compilation_unit.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache-inl.h"
 #include "scoped_thread_state_change.h"
@@ -133,7 +134,7 @@
                                                     ArtMember* member ATTRIBUTE_UNUSED,
                                                     mirror::DexCache* dex_cache ATTRIBUTE_UNUSED,
                                                     uint32_t field_idx ATTRIBUTE_UNUSED) {
-  // Not defined for ArtMember values other than ArtField or mirror::ArtMethod.
+  // Not defined for ArtMember values other than ArtField or ArtMethod.
   UNREACHABLE();
 }
 
@@ -147,10 +148,10 @@
 }
 
 template <>
-inline bool CompilerDriver::CanAccessResolvedMember<mirror::ArtMethod>(
+inline bool CompilerDriver::CanAccessResolvedMember<ArtMethod>(
     mirror::Class* referrer_class,
     mirror::Class* access_to,
-    mirror::ArtMethod* method,
+    ArtMethod* method,
     mirror::DexCache* dex_cache,
     uint32_t field_idx) {
   return referrer_class->CanAccessResolvedMethod(access_to, method, dex_cache, field_idx);
@@ -217,7 +218,7 @@
 
 inline bool CompilerDriver::IsClassOfStaticMethodAvailableToReferrer(
     mirror::DexCache* dex_cache, mirror::Class* referrer_class,
-    mirror::ArtMethod* resolved_method, uint16_t method_idx, uint32_t* storage_index) {
+    ArtMethod* resolved_method, uint16_t method_idx, uint32_t* storage_index) {
   std::pair<bool, bool> result = IsClassOfStaticMemberAvailableToReferrer(
       dex_cache, referrer_class, resolved_method, method_idx, storage_index);
   // Only the first member of `result` is meaningful, as there is no
@@ -239,15 +240,14 @@
   return fields_class == referrer_class || fields_class->IsInitialized();
 }
 
-inline mirror::ArtMethod* CompilerDriver::ResolveMethod(
+inline ArtMethod* CompilerDriver::ResolveMethod(
     ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
     Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
     uint32_t method_idx, InvokeType invoke_type, bool check_incompatible_class_change) {
   DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile());
   DCHECK_EQ(class_loader.Get(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()));
-  mirror::ArtMethod* resolved_method = mUnit->GetClassLinker()->ResolveMethod(
-      *mUnit->GetDexFile(), method_idx, dex_cache, class_loader, NullHandle<mirror::ArtMethod>(),
-      invoke_type);
+  ArtMethod* resolved_method = mUnit->GetClassLinker()->ResolveMethod(
+      *mUnit->GetDexFile(), method_idx, dex_cache, class_loader, nullptr, invoke_type);
   DCHECK_EQ(resolved_method == nullptr, soa.Self()->IsExceptionPending());
   if (UNLIKELY(resolved_method == nullptr)) {
     // Clean up any exception left by type resolution.
@@ -263,7 +263,7 @@
 }
 
 inline void CompilerDriver::GetResolvedMethodDexFileLocation(
-    mirror::ArtMethod* resolved_method, const DexFile** declaring_dex_file,
+    ArtMethod* resolved_method, const DexFile** declaring_dex_file,
     uint16_t* declaring_class_idx, uint16_t* declaring_method_idx) {
   mirror::Class* declaring_class = resolved_method->GetDeclaringClass();
   *declaring_dex_file = declaring_class->GetDexCache()->GetDexFile();
@@ -272,7 +272,7 @@
 }
 
 inline uint16_t CompilerDriver::GetResolvedMethodVTableIndex(
-    mirror::ArtMethod* resolved_method, InvokeType type) {
+    ArtMethod* resolved_method, InvokeType type) {
   if (type == kVirtual || type == kSuper) {
     return resolved_method->GetMethodIndex();
   } else if (type == kInterface) {
@@ -285,7 +285,7 @@
 inline int CompilerDriver::IsFastInvoke(
     ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
     Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
-    mirror::Class* referrer_class, mirror::ArtMethod* resolved_method, InvokeType* invoke_type,
+    mirror::Class* referrer_class, ArtMethod* resolved_method, InvokeType* invoke_type,
     MethodReference* target_method, const MethodReference* devirt_target,
     uintptr_t* direct_code, uintptr_t* direct_method) {
   // Don't try to fast-path if we don't understand the caller's class.
@@ -305,10 +305,12 @@
       (*invoke_type == kVirtual) && (resolved_method->IsFinal() || methods_class->IsFinal());
   // For invoke-super, ensure the vtable index will be correct to dispatch in the vtable of
   // the super class.
+  const size_t pointer_size = InstructionSetPointerSize(GetInstructionSet());
   bool can_sharpen_super_based_on_type = same_dex_file && (*invoke_type == kSuper) &&
       (referrer_class != methods_class) && referrer_class->IsSubClass(methods_class) &&
       resolved_method->GetMethodIndex() < methods_class->GetVTableLength() &&
-      (methods_class->GetVTableEntry(resolved_method->GetMethodIndex()) == resolved_method) &&
+      (methods_class->GetVTableEntry(
+          resolved_method->GetMethodIndex(), pointer_size) == resolved_method) &&
       !resolved_method->IsAbstract();
 
   if (can_sharpen_virtual_based_on_type || can_sharpen_super_based_on_type) {
@@ -316,7 +318,8 @@
     // dex cache, check that this resolved method is where we expect it.
     CHECK_EQ(target_method->dex_file, mUnit->GetDexFile());
     DCHECK_EQ(dex_cache.Get(), mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()));
-    CHECK_EQ(referrer_class->GetDexCache()->GetResolvedMethod(target_method->dex_method_index),
+    CHECK_EQ(referrer_class->GetDexCache()->GetResolvedMethod(
+        target_method->dex_method_index, pointer_size),
              resolved_method) << PrettyMethod(resolved_method);
     int stats_flags = kFlagMethodResolved;
     GetCodeAndMethodForDirectCall(/*out*/invoke_type,
@@ -336,21 +339,18 @@
 
   if ((*invoke_type == kVirtual || *invoke_type == kInterface) && devirt_target != nullptr) {
     // Post-verification callback recorded a more precise invoke target based on its type info.
-    mirror::ArtMethod* called_method;
+    ArtMethod* called_method;
     ClassLinker* class_linker = mUnit->GetClassLinker();
     if (LIKELY(devirt_target->dex_file == mUnit->GetDexFile())) {
-      called_method = class_linker->ResolveMethod(*devirt_target->dex_file,
-                                                  devirt_target->dex_method_index, dex_cache,
-                                                  class_loader, NullHandle<mirror::ArtMethod>(),
-                                                  kVirtual);
+      called_method = class_linker->ResolveMethod(
+          *devirt_target->dex_file, devirt_target->dex_method_index, dex_cache, class_loader,
+          nullptr, kVirtual);
     } else {
       StackHandleScope<1> hs(soa.Self());
-      Handle<mirror::DexCache> target_dex_cache(
-          hs.NewHandle(class_linker->FindDexCache(*devirt_target->dex_file)));
-      called_method = class_linker->ResolveMethod(*devirt_target->dex_file,
-                                                  devirt_target->dex_method_index,
-                                                  target_dex_cache, class_loader,
-                                                  NullHandle<mirror::ArtMethod>(), kVirtual);
+      auto target_dex_cache(hs.NewHandle(class_linker->FindDexCache(*devirt_target->dex_file)));
+      called_method = class_linker->ResolveMethod(
+          *devirt_target->dex_file, devirt_target->dex_method_index, target_dex_cache,
+          class_loader, nullptr, kVirtual);
     }
     CHECK(called_method != nullptr);
     CHECK(!called_method->IsAbstract());
@@ -389,7 +389,7 @@
 }
 
 inline bool CompilerDriver::IsMethodsClassInitialized(mirror::Class* referrer_class,
-                                                      mirror::ArtMethod* resolved_method) {
+                                                      ArtMethod* resolved_method) {
   if (!resolved_method->IsStatic()) {
     return true;
   }
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index f988812..5ff8a53 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -28,6 +28,7 @@
 #endif
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/stl_util.h"
 #include "base/time_utils.h"
 #include "base/timing_logger.h"
@@ -50,8 +51,8 @@
 #include "runtime.h"
 #include "gc/accounting/card_table-inl.h"
 #include "gc/accounting/heap_bitmap.h"
+#include "gc/space/image_space.h"
 #include "gc/space/space.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
@@ -542,7 +543,7 @@
   }
 }
 
-void CompilerDriver::CompileOne(Thread* self, mirror::ArtMethod* method, TimingLogger* timings) {
+void CompilerDriver::CompileOne(Thread* self, ArtMethod* method, TimingLogger* timings) {
   DCHECK(!Runtime::Current()->IsStarted());
   jobject jclass_loader;
   const DexFile* dex_file;
@@ -586,7 +587,7 @@
   self->TransitionFromSuspendedToRunnable();
 }
 
-CompiledMethod* CompilerDriver::CompileMethod(Thread* self, mirror::ArtMethod* method) {
+CompiledMethod* CompilerDriver::CompileMethod(Thread* self, ArtMethod* method) {
   const uint32_t method_idx = method->GetDexMethodIndex();
   const uint32_t access_flags = method->GetAccessFlags();
   const InvokeType invoke_type = method->GetInvokeType();
@@ -688,8 +689,8 @@
   return methods_to_compile_->find(tmp.c_str()) != methods_to_compile_->end();
 }
 
-static void ResolveExceptionsForMethod(MutableHandle<mirror::ArtMethod> method_handle,
-    std::set<std::pair<uint16_t, const DexFile*>>& exceptions_to_resolve)
+static void ResolveExceptionsForMethod(
+    ArtMethod* method_handle, std::set<std::pair<uint16_t, const DexFile*>>& exceptions_to_resolve)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   const DexFile::CodeItem* code_item = method_handle->GetCodeItem();
   if (code_item == nullptr) {
@@ -728,17 +729,14 @@
 
 static bool ResolveCatchBlockExceptionsClassVisitor(mirror::Class* c, void* arg)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  std::set<std::pair<uint16_t, const DexFile*>>* exceptions_to_resolve =
+  auto* exceptions_to_resolve =
       reinterpret_cast<std::set<std::pair<uint16_t, const DexFile*>>*>(arg);
-  StackHandleScope<1> hs(Thread::Current());
-  MutableHandle<mirror::ArtMethod> method_handle(hs.NewHandle<mirror::ArtMethod>(nullptr));
-  for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
-    method_handle.Assign(c->GetVirtualMethod(i));
-    ResolveExceptionsForMethod(method_handle, *exceptions_to_resolve);
+  const auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+  for (auto& m : c->GetVirtualMethods(pointer_size)) {
+    ResolveExceptionsForMethod(&m, *exceptions_to_resolve);
   }
-  for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
-    method_handle.Assign(c->GetDirectMethod(i));
-    ResolveExceptionsForMethod(method_handle, *exceptions_to_resolve);
+  for (auto& m : c->GetDirectMethods(pointer_size)) {
+    ResolveExceptionsForMethod(&m, *exceptions_to_resolve);
   }
   return true;
 }
@@ -826,6 +824,7 @@
   // Make a copy of the handle so that we don't clobber it doing Assign.
   MutableHandle<mirror::Class> klass(hs.NewHandle(c.Get()));
   std::string temp;
+  const size_t pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
   while (!klass->IsObjectClass()) {
     const char* descriptor = klass->GetDescriptor(&temp);
     std::pair<std::unordered_set<std::string>::iterator, bool> result =
@@ -839,6 +838,12 @@
       MaybeAddToImageClasses(hs2.NewHandle(mirror::Class::GetDirectInterface(self, klass, i)),
                              image_classes);
     }
+    for (auto& m : c->GetVirtualMethods(pointer_size)) {
+      if (m.IsMiranda() || (true)) {
+        StackHandleScope<1> hs2(self);
+        MaybeAddToImageClasses(hs2.NewHandle(m.GetDeclaringClass()), image_classes);
+      }
+    }
     if (klass->IsArrayClass()) {
       StackHandleScope<1> hs2(self);
       MaybeAddToImageClasses(hs2.NewHandle(klass->GetComponentType()), image_classes);
@@ -855,10 +860,7 @@
                                    Thread* self, ClassLinker* linker, std::string* error_msg) {
     std::unique_ptr<ClinitImageUpdate> res(new ClinitImageUpdate(image_class_descriptors, self,
                                                                  linker));
-    if (res->art_method_class_ == nullptr) {
-      *error_msg = "Could not find ArtMethod class.";
-      return nullptr;
-    } else if (res->dex_cache_class_ == nullptr) {
+    if (res->dex_cache_class_ == nullptr) {
       *error_msg = "Could not find DexCache class.";
       return nullptr;
     }
@@ -903,8 +905,6 @@
     old_cause_ = self->StartAssertNoThreadSuspension("Boot image closure");
 
     // Find the interesting classes.
-    art_method_class_ = linker->LookupClass(self, "Ljava/lang/reflect/ArtMethod;",
-        ComputeModifiedUtf8Hash("Ljava/lang/reflect/ArtMethod;"), nullptr);
     dex_cache_class_ = linker->LookupClass(self, "Ljava/lang/DexCache;",
         ComputeModifiedUtf8Hash("Ljava/lang/DexCache;"), nullptr);
 
@@ -922,7 +922,8 @@
       data->image_classes_.push_back(klass);
     } else {
       // Check whether it is initialized and has a clinit. They must be kept, too.
-      if (klass->IsInitialized() && klass->FindClassInitializer() != nullptr) {
+      if (klass->IsInitialized() && klass->FindClassInitializer(
+          Runtime::Current()->GetClassLinker()->GetImagePointerSize()) != nullptr) {
         data->image_classes_.push_back(klass);
       }
     }
@@ -950,9 +951,9 @@
       VisitClinitClassesObject(object->GetClass());
     }
 
-    // If it is not a dex cache or an ArtMethod, visit all references.
+    // If it is not a DexCache, visit all references.
     mirror::Class* klass = object->GetClass();
-    if (klass != art_method_class_ && klass != dex_cache_class_) {
+    if (klass != dex_cache_class_) {
       object->VisitReferences<false /* visit class */>(*this, *this);
     }
   }
@@ -960,7 +961,6 @@
   mutable std::unordered_set<mirror::Object*> marked_objects_;
   std::unordered_set<std::string>* const image_class_descriptors_;
   std::vector<mirror::Class*> image_classes_;
-  const mirror::Class* art_method_class_;
   const mirror::Class* dex_cache_class_;
   Thread* const self_;
   const char* old_cause_;
@@ -1334,7 +1334,7 @@
 void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType* type, InvokeType sharp_type,
                                                    bool no_guarantee_of_dex_cache_entry,
                                                    const mirror::Class* referrer_class,
-                                                   mirror::ArtMethod* method,
+                                                   ArtMethod* method,
                                                    int* stats_flags,
                                                    MethodReference* target_method,
                                                    uintptr_t* direct_code,
@@ -1347,6 +1347,8 @@
   *direct_method = 0;
   Runtime* const runtime = Runtime::Current();
   gc::Heap* const heap = runtime->GetHeap();
+  auto* cl = runtime->GetClassLinker();
+  const auto pointer_size = cl->GetImagePointerSize();
   bool use_dex_cache = GetCompilerOptions().GetCompilePic();  // Off by default
   const bool compiling_boot = heap->IsCompilingBoot();
   // TODO This is somewhat hacky. We should refactor all of this invoke codepath.
@@ -1375,7 +1377,7 @@
   if (runtime->UseJit()) {
     // If we are the JIT, then don't allow a direct call to the interpreter bridge since this will
     // never be updated even after we compile the method.
-    if (runtime->GetClassLinker()->IsQuickToInterpreterBridge(
+    if (cl->IsQuickToInterpreterBridge(
         reinterpret_cast<const void*>(compiler_->GetEntryPointOf(method)))) {
       use_dex_cache = true;
     }
@@ -1389,8 +1391,7 @@
       is_in_image = IsImageClass(method->GetDeclaringClassDescriptor());
     } else {
       is_in_image = instruction_set_ != kX86 && instruction_set_ != kX86_64 &&
-                    Runtime::Current()->GetHeap()->FindSpaceFromObject(method->GetDeclaringClass(),
-                                                                       false)->IsImageSpace();
+                    heap->FindSpaceFromObject(method->GetDeclaringClass(), false)->IsImageSpace();
     }
     if (!is_in_image) {
       // We can only branch directly to Methods that are resolved in the DexCache.
@@ -1403,14 +1404,14 @@
   bool must_use_direct_pointers = false;
   mirror::DexCache* dex_cache = declaring_class->GetDexCache();
   if (target_method->dex_file == dex_cache->GetDexFile() &&
-    !(runtime->UseJit() && dex_cache->GetResolvedMethod(method->GetDexMethodIndex()) == nullptr)) {
+    !(runtime->UseJit() && dex_cache->GetResolvedMethod(
+        method->GetDexMethodIndex(), pointer_size) == nullptr)) {
     target_method->dex_method_index = method->GetDexMethodIndex();
   } else {
     if (no_guarantee_of_dex_cache_entry) {
       // See if the method is also declared in this dex cache.
-      uint32_t dex_method_idx =
-          method->FindDexMethodIndexInOtherDexFile(*target_method->dex_file,
-                                                   target_method->dex_method_index);
+      uint32_t dex_method_idx = method->FindDexMethodIndexInOtherDexFile(
+          *target_method->dex_file, target_method->dex_method_index);
       if (dex_method_idx != DexFile::kDexNoIndex) {
         target_method->dex_method_index = dex_method_idx;
       } else {
@@ -1431,7 +1432,13 @@
       *type = sharp_type;
     }
   } else {
-    bool method_in_image = heap->FindSpaceFromObject(method, false)->IsImageSpace();
+    auto* image_space = heap->GetImageSpace();
+    bool method_in_image = false;
+    if (image_space != nullptr) {
+      const auto& method_section = image_space->GetImageHeader().GetMethodsSection();
+      method_in_image = method_section.Contains(
+          reinterpret_cast<uint8_t*>(method) - image_space->Begin());
+    }
     if (method_in_image || compiling_boot || runtime->UseJit()) {
       // We know we must be able to get to the method in the image, so use that pointer.
       // In the case where we are the JIT, we can always use direct pointers since we know where
@@ -1469,21 +1476,16 @@
   int stats_flags = 0;
   ScopedObjectAccess soa(Thread::Current());
   // Try to resolve the method and compiling method's class.
-  mirror::ArtMethod* resolved_method;
-  mirror::Class* referrer_class;
   StackHandleScope<3> hs(soa.Self());
   Handle<mirror::DexCache> dex_cache(
       hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
       soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())));
-  {
-    uint32_t method_idx = target_method->dex_method_index;
-    Handle<mirror::ArtMethod> resolved_method_handle(hs.NewHandle(
-        ResolveMethod(soa, dex_cache, class_loader, mUnit, method_idx, orig_invoke_type)));
-    referrer_class = (resolved_method_handle.Get() != nullptr)
-        ? ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit) : nullptr;
-    resolved_method = resolved_method_handle.Get();
-  }
+  uint32_t method_idx = target_method->dex_method_index;
+  ArtMethod* resolved_method = ResolveMethod(
+      soa, dex_cache, class_loader, mUnit, method_idx, orig_invoke_type);
+  auto h_referrer_class = hs.NewHandle(resolved_method != nullptr ?
+      ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit) : nullptr);
   bool result = false;
   if (resolved_method != nullptr) {
     *vtable_idx = GetResolvedMethodVTableIndex(resolved_method, orig_invoke_type);
@@ -1492,13 +1494,13 @@
       const MethodReference* devirt_target = mUnit->GetVerifiedMethod()->GetDevirtTarget(dex_pc);
 
       stats_flags = IsFastInvoke(
-          soa, dex_cache, class_loader, mUnit, referrer_class, resolved_method,
+          soa, dex_cache, class_loader, mUnit, h_referrer_class.Get(), resolved_method,
           invoke_type, target_method, devirt_target, direct_code, direct_method);
       result = stats_flags != 0;
     } else {
       // Devirtualization not enabled. Inline IsFastInvoke(), dropping the devirtualization parts.
-      if (UNLIKELY(referrer_class == nullptr) ||
-          UNLIKELY(!referrer_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
+      if (UNLIKELY(h_referrer_class.Get() == nullptr) ||
+          UNLIKELY(!h_referrer_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
                                                             resolved_method, dex_cache.Get(),
                                                             target_method->dex_method_index)) ||
           *invoke_type == kSuper) {
@@ -1506,8 +1508,9 @@
       } else {
         // Sharpening failed so generate a regular resolved method dispatch.
         stats_flags = kFlagMethodResolved;
-        GetCodeAndMethodForDirectCall(invoke_type, *invoke_type, false, referrer_class, resolved_method,
-                                      &stats_flags, target_method, direct_code, direct_method);
+        GetCodeAndMethodForDirectCall(
+            invoke_type, *invoke_type, false, h_referrer_class.Get(), resolved_method, &stats_flags,
+            target_method, direct_code, direct_method);
         result = true;
       }
     }
@@ -1773,20 +1776,18 @@
     }
     if (resolve_fields_and_methods) {
       while (it.HasNextDirectMethod()) {
-        mirror::ArtMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(),
-                                                                dex_cache, class_loader,
-                                                                NullHandle<mirror::ArtMethod>(),
-                                                                it.GetMethodInvokeType(class_def));
+        ArtMethod* method = class_linker->ResolveMethod(
+            dex_file, it.GetMemberIndex(), dex_cache, class_loader, nullptr,
+            it.GetMethodInvokeType(class_def));
         if (method == nullptr) {
           CheckAndClearResolveException(soa.Self());
         }
         it.Next();
       }
       while (it.HasNextVirtualMethod()) {
-        mirror::ArtMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(),
-                                                                dex_cache, class_loader,
-                                                                NullHandle<mirror::ArtMethod>(),
-                                                                it.GetMethodInvokeType(class_def));
+        ArtMethod* method = class_linker->ResolveMethod(
+            dex_file, it.GetMemberIndex(), dex_cache, class_loader, nullptr,
+            it.GetMethodInvokeType(class_def));
         if (method == nullptr) {
           CheckAndClearResolveException(soa.Self());
         }
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 2cc2409..68c905e 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -116,11 +116,11 @@
                   TimingLogger* timings)
       LOCKS_EXCLUDED(Locks::mutator_lock_);
 
-  CompiledMethod* CompileMethod(Thread* self, mirror::ArtMethod*)
+  CompiledMethod* CompileMethod(Thread* self, ArtMethod*)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) WARN_UNUSED;
 
   // Compile a single Method.
-  void CompileOne(Thread* self, mirror::ArtMethod* method, TimingLogger* timings)
+  void CompileOne(Thread* self, ArtMethod* method, TimingLogger* timings)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   VerificationResults* GetVerificationResults() const {
@@ -288,7 +288,7 @@
   // return DexFile::kDexNoIndex through `storage_index`.
   bool IsClassOfStaticMethodAvailableToReferrer(mirror::DexCache* dex_cache,
                                                 mirror::Class* referrer_class,
-                                                mirror::ArtMethod* resolved_method,
+                                                ArtMethod* resolved_method,
                                                 uint16_t method_idx,
                                                 uint32_t* storage_index)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -303,7 +303,7 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Resolve a method. Returns null on failure, including incompatible class change.
-  mirror::ArtMethod* ResolveMethod(
+  ArtMethod* ResolveMethod(
       ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
       Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
       uint32_t method_idx, InvokeType invoke_type, bool check_incompatible_class_change = true)
@@ -311,13 +311,13 @@
 
   // Get declaration location of a resolved field.
   void GetResolvedMethodDexFileLocation(
-      mirror::ArtMethod* resolved_method, const DexFile** declaring_dex_file,
+      ArtMethod* resolved_method, const DexFile** declaring_dex_file,
       uint16_t* declaring_class_idx, uint16_t* declaring_method_idx)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get the index in the vtable of the method.
   uint16_t GetResolvedMethodVTableIndex(
-      mirror::ArtMethod* resolved_method, InvokeType type)
+      ArtMethod* resolved_method, InvokeType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Can we fast-path an INVOKE? If no, returns 0. If yes, returns a non-zero opaque flags value
@@ -325,7 +325,7 @@
   int IsFastInvoke(
       ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
       Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
-      mirror::Class* referrer_class, mirror::ArtMethod* resolved_method, InvokeType* invoke_type,
+      mirror::Class* referrer_class, ArtMethod* resolved_method, InvokeType* invoke_type,
       MethodReference* target_method, const MethodReference* devirt_target,
       uintptr_t* direct_code, uintptr_t* direct_method)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -333,7 +333,7 @@
   // Is method's class initialized for an invoke?
   // For static invokes to determine whether we need to consider potential call to <clinit>().
   // For non-static invokes, assuming a non-null reference, the class is always initialized.
-  bool IsMethodsClassInitialized(mirror::Class* referrer_class, mirror::ArtMethod* resolved_method)
+  bool IsMethodsClassInitialized(mirror::Class* referrer_class, ArtMethod* resolved_method)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get the layout of dex cache arrays for a dex file. Returns invalid layout if the
@@ -526,7 +526,7 @@
                                      InvokeType sharp_type,
                                      bool no_guarantee_of_dex_cache_entry,
                                      const mirror::Class* referrer_class,
-                                     mirror::ArtMethod* method,
+                                     ArtMethod* method,
                                      /*out*/int* stats_flags,
                                      MethodReference* target_method,
                                      uintptr_t* direct_code, uintptr_t* direct_method)
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 5085f32..ba03f5a 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -20,11 +20,11 @@
 #include <stdio.h>
 #include <memory>
 
+#include "art_method-inl.h"
 #include "class_linker-inl.h"
 #include "common_compiler_test.h"
 #include "dex_file.h"
 #include "gc/heap.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache-inl.h"
@@ -85,11 +85,12 @@
           hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
       mirror::Class* c = class_linker->FindClass(soa.Self(), descriptor, loader);
       CHECK(c != nullptr);
-      for (size_t j = 0; j < c->NumDirectMethods(); j++) {
-        MakeExecutable(c->GetDirectMethod(j));
+      const auto pointer_size = class_linker->GetImagePointerSize();
+      for (auto& m : c->GetDirectMethods(pointer_size)) {
+        MakeExecutable(&m);
       }
-      for (size_t j = 0; j < c->NumVirtualMethods(); j++) {
-        MakeExecutable(c->GetVirtualMethod(j));
+      for (auto& m : c->GetVirtualMethods(pointer_size)) {
+        MakeExecutable(&m);
       }
     }
   }
@@ -120,8 +121,10 @@
                               << " " << dex.GetTypeDescriptor(dex.GetTypeId(i));
   }
   EXPECT_EQ(dex.NumMethodIds(), dex_cache->NumResolvedMethods());
+  auto* cl = Runtime::Current()->GetClassLinker();
+  auto pointer_size = cl->GetImagePointerSize();
   for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
-    mirror::ArtMethod* method = dex_cache->GetResolvedMethod(i);
+    ArtMethod* method = dex_cache->GetResolvedMethod(i, pointer_size);
     EXPECT_TRUE(method != nullptr) << "method_idx=" << i
                                 << " " << dex.GetMethodDeclaringClassDescriptor(dex.GetMethodId(i))
                                 << " " << dex.GetMethodName(dex.GetMethodId(i));
@@ -131,7 +134,7 @@
   }
   EXPECT_EQ(dex.NumFieldIds(), dex_cache->NumResolvedFields());
   for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
-    ArtField* field = Runtime::Current()->GetClassLinker()->GetResolvedField(i, dex_cache);
+    ArtField* field = cl->GetResolvedField(i, dex_cache);
     EXPECT_TRUE(field != nullptr) << "field_idx=" << i
                                << " " << dex.GetFieldDeclaringClassDescriptor(dex.GetFieldId(i))
                                << " " << dex.GetFieldName(dex.GetFieldId(i));
@@ -157,12 +160,15 @@
 
   // Create a jobj_ of ConcreteClass, NOT AbstractClass.
   jclass c_class = env_->FindClass("ConcreteClass");
+
   jmethodID constructor = env_->GetMethodID(c_class, "<init>", "()V");
+
   jobject jobj_ = env_->NewObject(c_class, constructor);
   ASSERT_TRUE(jobj_ != nullptr);
 
   // Force non-virtual call to AbstractClass foo, will throw AbstractMethodError exception.
   env_->CallNonvirtualVoidMethod(jobj_, class_, mid_);
+
   EXPECT_EQ(env_->ExceptionCheck(), JNI_TRUE);
   jthrowable exception = env_->ExceptionOccurred();
   env_->ExceptionClear();
@@ -212,11 +218,10 @@
 
   std::unique_ptr<std::unordered_set<std::string>> expected(GetCompiledMethods());
 
-  for (int32_t i = 0; static_cast<uint32_t>(i) < klass->NumDirectMethods(); i++) {
-    mirror::ArtMethod* m = klass->GetDirectMethod(i);
-    std::string name = PrettyMethod(m, true);
-    const void* code =
-        m->GetEntryPointFromQuickCompiledCodePtrSize(InstructionSetPointerSize(kRuntimeISA));
+  const auto pointer_size = class_linker->GetImagePointerSize();
+  for (auto& m : klass->GetDirectMethods(pointer_size)) {
+    std::string name = PrettyMethod(&m, true);
+    const void* code = m.GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
     ASSERT_NE(code, nullptr);
     if (expected->find(name) != expected->end()) {
       expected->erase(name);
diff --git a/compiler/elf_writer.cc b/compiler/elf_writer.cc
index f75638d..4219d97 100644
--- a/compiler/elf_writer.cc
+++ b/compiler/elf_writer.cc
@@ -16,6 +16,7 @@
 
 #include "elf_writer.h"
 
+#include "art_method-inl.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
 #include "dex_file-inl.h"
@@ -23,7 +24,6 @@
 #include "driver/compiler_driver.h"
 #include "elf_file.h"
 #include "invoke_type.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/object-inl.h"
 #include "oat.h"
 #include "scoped_thread_state_change.h"
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index eaf3489..dbdd350 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -111,8 +111,9 @@
     ImageHeader image_header;
     ASSERT_EQ(file->ReadFully(&image_header, sizeof(image_header)), true);
     ASSERT_TRUE(image_header.IsValid());
-    ASSERT_GE(image_header.GetImageBitmapOffset(), sizeof(image_header));
-    ASSERT_NE(0U, image_header.GetImageBitmapSize());
+    const auto& bitmap_section = image_header.GetImageSection(ImageHeader::kSectionImageBitmap);
+    ASSERT_GE(bitmap_section.Offset(), sizeof(image_header));
+    ASSERT_NE(0U, bitmap_section.Size());
 
     gc::Heap* heap = Runtime::Current()->GetHeap();
     ASSERT_TRUE(!heap->GetContinuousSpaces().empty());
@@ -120,7 +121,7 @@
     ASSERT_FALSE(space->IsImageSpace());
     ASSERT_TRUE(space != nullptr);
     ASSERT_TRUE(space->IsMallocSpace());
-    ASSERT_GE(sizeof(image_header) + space->Size(), static_cast<size_t>(file->GetLength()));
+    ASSERT_LE(space->Size(), static_cast<size_t>(file->GetLength()));
   }
 
   ASSERT_TRUE(compiler_driver_->GetImageClasses() != nullptr);
@@ -195,25 +196,23 @@
 TEST_F(ImageTest, ImageHeaderIsValid) {
     uint32_t image_begin = ART_BASE_ADDRESS;
     uint32_t image_size_ = 16 * KB;
-    uint32_t image_bitmap_offset = 0;
-    uint32_t image_bitmap_size = 0;
     uint32_t image_roots = ART_BASE_ADDRESS + (1 * KB);
     uint32_t oat_checksum = 0;
     uint32_t oat_file_begin = ART_BASE_ADDRESS + (4 * KB);  // page aligned
     uint32_t oat_data_begin = ART_BASE_ADDRESS + (8 * KB);  // page aligned
     uint32_t oat_data_end = ART_BASE_ADDRESS + (9 * KB);
     uint32_t oat_file_end = ART_BASE_ADDRESS + (10 * KB);
+    ImageSection sections[ImageHeader::kSectionCount];
     ImageHeader image_header(image_begin,
                              image_size_,
-                             0u, 0u,
-                             image_bitmap_offset,
-                             image_bitmap_size,
+                             sections,
                              image_roots,
                              oat_checksum,
                              oat_file_begin,
                              oat_data_begin,
                              oat_data_end,
                              oat_file_end,
+                             sizeof(void*),
                              /*compile_pic*/false);
     ASSERT_TRUE(image_header.IsValid());
 
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 02a2588..11743f3 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -23,6 +23,7 @@
 #include <vector>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker-inl.h"
@@ -43,11 +44,12 @@
 #include "intern_table.h"
 #include "linear_alloc.h"
 #include "lock_word.h"
-#include "mirror/art_method-inl.h"
+#include "mirror/abstract_method.h"
 #include "mirror/array-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache-inl.h"
+#include "mirror/method.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/string-inl.h"
@@ -58,10 +60,8 @@
 #include "handle_scope-inl.h"
 #include "utils/dex_cache_arrays_layout-inl.h"
 
-using ::art::mirror::ArtMethod;
 using ::art::mirror::Class;
 using ::art::mirror::DexCache;
-using ::art::mirror::EntryPointFromInterpreter;
 using ::art::mirror::Object;
 using ::art::mirror::ObjectArray;
 using ::art::mirror::String;
@@ -169,10 +169,11 @@
   ElfWriter::GetOatElfInformation(oat_file.get(), &oat_loaded_size, &oat_data_offset);
 
   Thread::Current()->TransitionFromSuspendedToRunnable();
+
   CreateHeader(oat_loaded_size, oat_data_offset);
+  CopyAndFixupNativeData();
   // TODO: heap validation can't handle these fix up passes.
   Runtime::Current()->GetHeap()->DisableObjectValidation();
-  CopyAndFixupNativeData();
   CopyAndFixupObjects();
   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
 
@@ -195,9 +196,8 @@
     return EXIT_FAILURE;
   }
 
-  // Write out the image + fields.
-  const auto write_count = image_header->GetImageSize() + image_header->GetArtFieldsSize();
-  CHECK_EQ(image_end_, image_header->GetImageSize());
+  // Write out the image + fields + methods.
+  const auto write_count = image_header->GetImageSize();
   if (!image_file->WriteFully(image_->Begin(), write_count)) {
     PLOG(ERROR) << "Failed to write image file " << image_filename;
     image_file->Erase();
@@ -205,17 +205,16 @@
   }
 
   // Write out the image bitmap at the page aligned start of the image end.
-  CHECK_ALIGNED(image_header->GetImageBitmapOffset(), kPageSize);
+  const auto& bitmap_section = image_header->GetImageSection(ImageHeader::kSectionImageBitmap);
+  CHECK_ALIGNED(bitmap_section.Offset(), kPageSize);
   if (!image_file->Write(reinterpret_cast<char*>(image_bitmap_->Begin()),
-                         image_header->GetImageBitmapSize(),
-                         image_header->GetImageBitmapOffset())) {
+                         bitmap_section.Size(), bitmap_section.Offset())) {
     PLOG(ERROR) << "Failed to write image file " << image_filename;
     image_file->Erase();
     return false;
   }
 
-  CHECK_EQ(image_header->GetImageBitmapOffset() + image_header->GetImageBitmapSize(),
-           static_cast<size_t>(image_file->GetLength()));
+  CHECK_EQ(bitmap_section.End(), static_cast<size_t>(image_file->GetLength()));
   if (image_file->FlushCloseOrErase() != 0) {
     PLOG(ERROR) << "Failed to flush and close image file " << image_filename;
     return false;
@@ -245,9 +244,16 @@
   }
   // The object is already deflated from when we set the bin slot. Just overwrite the lock word.
   object->SetLockWord(LockWord::FromForwardingAddress(offset), false);
+  DCHECK_EQ(object->GetLockWord(false).ReadBarrierState(), 0u);
   DCHECK(IsImageOffsetAssigned(object));
 }
 
+void ImageWriter::UpdateImageOffset(mirror::Object* obj, uintptr_t offset) {
+  DCHECK(IsImageOffsetAssigned(obj)) << obj << " " << offset;
+  obj->SetLockWord(LockWord::FromForwardingAddress(offset), false);
+  DCHECK_EQ(obj->GetLockWord(false).ReadBarrierState(), 0u);
+}
+
 void ImageWriter::AssignImageOffset(mirror::Object* object, ImageWriter::BinSlot bin_slot) {
   DCHECK(object != nullptr);
   DCHECK_NE(image_objects_offset_begin_, 0u);
@@ -304,6 +310,7 @@
   }
   object->SetLockWord(LockWord::FromForwardingAddress(static_cast<uint32_t>(bin_slot)),
                       false);
+  DCHECK_EQ(object->GetLockWord(false).ReadBarrierState(), 0u);
   DCHECK(IsImageBinSlotAssigned(object));
 }
 
@@ -324,16 +331,18 @@
     auto strings_size = layout.StringsSize(dex_file->NumStringIds());
     dex_cache_array_indexes_.Put(
         dex_cache->GetResolvedTypes(),
-        DexCacheArrayLocation {size + layout.TypesOffset(), types_size});
+        DexCacheArrayLocation {size + layout.TypesOffset(), types_size, kBinRegular});
     dex_cache_array_indexes_.Put(
         dex_cache->GetResolvedMethods(),
-        DexCacheArrayLocation {size + layout.MethodsOffset(), methods_size});
+        DexCacheArrayLocation {size + layout.MethodsOffset(), methods_size, kBinArtMethodClean});
+    AddMethodPointerArray(dex_cache->GetResolvedMethods());
     dex_cache_array_indexes_.Put(
         dex_cache->GetResolvedFields(),
-        DexCacheArrayLocation {size + layout.FieldsOffset(), fields_size});
+        DexCacheArrayLocation {size + layout.FieldsOffset(), fields_size, kBinArtField});
+    pointer_arrays_.emplace(dex_cache->GetResolvedFields(), kBinArtField);
     dex_cache_array_indexes_.Put(
         dex_cache->GetStrings(),
-        DexCacheArrayLocation {size + layout.StringsOffset(), strings_size});
+        DexCacheArrayLocation {size + layout.StringsOffset(), strings_size, kBinRegular});
     size += layout.Size();
     CHECK_EQ(layout.Size(), types_size + methods_size + fields_size + strings_size);
   }
@@ -342,6 +351,23 @@
   bin_slot_sizes_[kBinDexCacheArray] = size;
 }
 
+void ImageWriter::AddMethodPointerArray(mirror::PointerArray* arr) {
+  DCHECK(arr != nullptr);
+  if (kIsDebugBuild) {
+    for (size_t i = 0, len = arr->GetLength(); i < len; i++) {
+      auto* method = arr->GetElementPtrSize<ArtMethod*>(i, target_ptr_size_);
+      if (method != nullptr && !method->IsRuntimeMethod()) {
+        auto* klass = method->GetDeclaringClass();
+        CHECK(klass == nullptr || IsImageClass(klass)) << PrettyClass(klass)
+            << " should be an image class";
+      }
+    }
+  }
+  // kBinArtMethodClean picked arbitrarily, just required to differentiate between ArtFields and
+  // ArtMethods.
+  pointer_arrays_.emplace(arr, kBinArtMethodClean);
+}
+
 void ImageWriter::AssignImageBinSlot(mirror::Object* object) {
   DCHECK(object != nullptr);
   size_t object_size = object->SizeOf();
@@ -393,6 +419,20 @@
       bin = kBinClassVerified;
       mirror::Class* klass = object->AsClass();
 
+      // Add non-embedded vtable to the pointer array table if there is one.
+      auto* vtable = klass->GetVTable();
+      if (vtable != nullptr) {
+        AddMethodPointerArray(vtable);
+      }
+      auto* iftable = klass->GetIfTable();
+      if (iftable != nullptr) {
+        for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
+          if (iftable->GetMethodArrayCount(i) > 0) {
+            AddMethodPointerArray(iftable->GetMethodArray(i));
+          }
+        }
+      }
+
       if (klass->GetStatus() == Class::kStatusInitialized) {
         bin = kBinClassInitialized;
 
@@ -417,26 +457,11 @@
           }
         }
       }
-    } else if (object->IsArtMethod<kVerifyNone>()) {
-      mirror::ArtMethod* art_method = down_cast<ArtMethod*>(object);
-      if (art_method->IsNative()) {
-        bin = kBinArtMethodNative;
-      } else {
-        mirror::Class* declaring_class = art_method->GetDeclaringClass();
-        if (declaring_class->GetStatus() != Class::kStatusInitialized) {
-          bin = kBinArtMethodNotInitialized;
-        } else {
-          // This is highly unlikely to dirty since there's no entry points to mutate.
-          bin = kBinArtMethodsManagedInitialized;
-        }
-      }
     } else if (object->GetClass<kVerifyNone>()->IsStringClass()) {
       bin = kBinString;  // Strings are almost always immutable (except for object header).
     } else if (object->IsArrayInstance()) {
       mirror::Class* klass = object->GetClass<kVerifyNone>();
-      auto* component_type = klass->GetComponentType();
-      if (!component_type->IsPrimitive() || component_type->IsPrimitiveInt() ||
-          component_type->IsPrimitiveLong()) {
+      if (klass->IsObjectArrayClass() || klass->IsIntArrayClass() || klass->IsLongArrayClass()) {
         auto it = dex_cache_array_indexes_.find(object);
         if (it != dex_cache_array_indexes_.end()) {
           bin = kBinDexCacheArray;
@@ -451,6 +476,7 @@
 
   size_t offset_delta = RoundUp(object_size, kObjectAlignment);  // 64-bit alignment
   if (bin != kBinDexCacheArray) {
+    DCHECK(dex_cache_array_indexes_.find(object) == dex_cache_array_indexes_.end()) << object;
     current_offset = bin_slot_sizes_[bin];  // How many bytes the current bin is at (aligned).
     // Move the current bin size up to accomodate the object we just assigned a bin slot.
     bin_slot_sizes_[bin] += offset_delta;
@@ -468,6 +494,15 @@
   DCHECK_LT(image_end_, image_->Size());
 }
 
+bool ImageWriter::WillMethodBeDirty(ArtMethod* m) const {
+  if (m->IsNative()) {
+    return true;
+  }
+  mirror::Class* declaring_class = m->GetDeclaringClass();
+  // Initialized is highly unlikely to dirty since there's no entry points to mutate.
+  return declaring_class == nullptr || declaring_class->GetStatus() != Class::kStatusInitialized;
+}
+
 bool ImageWriter::IsImageBinSlotAssigned(mirror::Object* object) const {
   DCHECK(object != nullptr);
 
@@ -604,6 +639,9 @@
 }
 
 bool ImageWriter::IsImageClass(Class* klass) {
+  if (klass == nullptr) {
+    return false;
+  }
   std::string temp;
   return compiler_driver_.IsImageClass(klass->GetDescriptor(&temp));
 }
@@ -619,6 +657,7 @@
   }
   Runtime* runtime = Runtime::Current();
   ClassLinker* class_linker = runtime->GetClassLinker();
+  Thread* self = Thread::Current();
 
   // Make a list of classes we would like to prune.
   std::set<std::string> non_image_classes;
@@ -634,27 +673,45 @@
   }
 
   // Clear references to removed classes from the DexCaches.
-  ArtMethod* resolution_method = runtime->GetResolutionMethod();
-  ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock());
-  size_t dex_cache_count = class_linker->GetDexCacheCount();
+  const ArtMethod* resolution_method = runtime->GetResolutionMethod();
+  size_t dex_cache_count;
+  {
+    ReaderMutexLock mu(self, *class_linker->DexLock());
+    dex_cache_count = class_linker->GetDexCacheCount();
+  }
   for (size_t idx = 0; idx < dex_cache_count; ++idx) {
-    DexCache* dex_cache = class_linker->GetDexCache(idx);
+    DexCache* dex_cache;
+    {
+      ReaderMutexLock mu(self, *class_linker->DexLock());
+      dex_cache = class_linker->GetDexCache(idx);
+    }
     for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
       Class* klass = dex_cache->GetResolvedType(i);
       if (klass != nullptr && !IsImageClass(klass)) {
         dex_cache->SetResolvedType(i, nullptr);
       }
     }
-    for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
-      ArtMethod* method = dex_cache->GetResolvedMethod(i);
-      if (method != nullptr && !IsImageClass(method->GetDeclaringClass())) {
-        dex_cache->SetResolvedMethod(i, resolution_method);
+    auto* resolved_methods = down_cast<mirror::PointerArray*>(dex_cache->GetResolvedMethods());
+    for (size_t i = 0, len = resolved_methods->GetLength(); i < len; i++) {
+      auto* method = resolved_methods->GetElementPtrSize<ArtMethod*>(i, target_ptr_size_);
+      if (method != nullptr) {
+        auto* declaring_class = method->GetDeclaringClass();
+        // Miranda methods may be held live by a class which was not an image class but have a
+        // declaring class which is an image class. Set it to the resolution method to be safe and
+        // prevent dangling pointers.
+        if (method->IsMiranda() || !IsImageClass(declaring_class)) {
+          resolved_methods->SetElementPtrSize(i, resolution_method, target_ptr_size_);
+        } else {
+          // Check that the class is still in the classes table.
+          DCHECK(class_linker->ClassInClassTable(declaring_class)) << "Class "
+              << PrettyClass(declaring_class) << " not in class linker table";
+        }
       }
     }
     for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
-      ArtField* field = dex_cache->GetResolvedField(i, sizeof(void*));
+      ArtField* field = dex_cache->GetResolvedField(i, target_ptr_size_);
       if (field != nullptr && !IsImageClass(field->GetDeclaringClass())) {
-        dex_cache->SetResolvedField(i, nullptr, sizeof(void*));
+        dex_cache->SetResolvedField(i, nullptr, target_ptr_size_);
       }
     }
     // Clean the dex field. It might have been populated during the initialization phase, but
@@ -757,19 +814,8 @@
   }
 
   // build an Object[] of the roots needed to restore the runtime
-  Handle<ObjectArray<Object>> image_roots(hs.NewHandle(
+  auto image_roots(hs.NewHandle(
       ObjectArray<Object>::Alloc(self, object_array_class.Get(), ImageHeader::kImageRootsMax)));
-  image_roots->Set<false>(ImageHeader::kResolutionMethod, runtime->GetResolutionMethod());
-  image_roots->Set<false>(ImageHeader::kImtConflictMethod, runtime->GetImtConflictMethod());
-  image_roots->Set<false>(ImageHeader::kImtUnimplementedMethod,
-                          runtime->GetImtUnimplementedMethod());
-  image_roots->Set<false>(ImageHeader::kDefaultImt, runtime->GetDefaultImt());
-  image_roots->Set<false>(ImageHeader::kCalleeSaveMethod,
-                          runtime->GetCalleeSaveMethod(Runtime::kSaveAll));
-  image_roots->Set<false>(ImageHeader::kRefsOnlySaveMethod,
-                          runtime->GetCalleeSaveMethod(Runtime::kRefsOnly));
-  image_roots->Set<false>(ImageHeader::kRefsAndArgsSaveMethod,
-                          runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs));
   image_roots->Set<false>(ImageHeader::kDexCaches, dex_caches.Get());
   image_roots->Set<false>(ImageHeader::kClassRoots, class_linker->GetClassRoots());
   for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
@@ -816,7 +862,7 @@
     // Walk static fields of a Class.
     if (h_obj->IsClass()) {
       size_t num_reference_static_fields = klass->NumReferenceStaticFields();
-      MemberOffset field_offset = klass->GetFirstReferenceStaticFieldOffset();
+      MemberOffset field_offset = klass->GetFirstReferenceStaticFieldOffset(target_ptr_size_);
       for (size_t i = 0; i < num_reference_static_fields; ++i) {
         mirror::Object* value = h_obj->GetFieldObject<mirror::Object>(field_offset);
         if (value != nullptr) {
@@ -825,21 +871,38 @@
         field_offset = MemberOffset(field_offset.Uint32Value() +
                                     sizeof(mirror::HeapReference<mirror::Object>));
       }
-
       // Visit and assign offsets for fields.
-      ArtField* fields[2] = { h_obj->AsClass()->GetSFields(), h_obj->AsClass()->GetIFields() };
-      size_t num_fields[2] = { h_obj->AsClass()->NumStaticFields(),
-          h_obj->AsClass()->NumInstanceFields() };
+      auto* as_klass = h_obj->AsClass();
+      ArtField* fields[] = { as_klass->GetSFields(), as_klass->GetIFields() };
+      size_t num_fields[] = { as_klass->NumStaticFields(), as_klass->NumInstanceFields() };
       for (size_t i = 0; i < 2; ++i) {
         for (size_t j = 0; j < num_fields[i]; ++j) {
           auto* field = fields[i] + j;
-          auto it = art_field_reloc_.find(field);
-          CHECK(it == art_field_reloc_.end()) << "Field at index " << i << ":" << j
+          auto it = native_object_reloc_.find(field);
+          CHECK(it == native_object_reloc_.end()) << "Field at index " << i << ":" << j
               << " already assigned " << PrettyField(field);
-          art_field_reloc_.emplace(field, bin_slot_sizes_[kBinArtField]);
+          native_object_reloc_.emplace(
+              field, NativeObjectReloc { bin_slot_sizes_[kBinArtField], kBinArtField });
           bin_slot_sizes_[kBinArtField] += sizeof(ArtField);
         }
       }
+      // Visit and assign offsets for methods.
+      IterationRange<StrideIterator<ArtMethod>> method_arrays[] = {
+          as_klass->GetDirectMethods(target_ptr_size_),
+          as_klass->GetVirtualMethods(target_ptr_size_)
+      };
+      for (auto& array : method_arrays) {
+        bool any_dirty = false;
+        size_t count = 0;
+        for (auto& m : array) {
+          any_dirty = any_dirty || WillMethodBeDirty(&m);
+          ++count;
+        }
+        for (auto& m : array) {
+          AssignMethodOffset(&m, any_dirty ? kBinArtMethodDirty : kBinArtMethodClean);
+        }
+        (any_dirty ? dirty_methods_ : clean_methods_) += count;
+      }
     } else if (h_obj->IsObjectArray()) {
       // Walk elements of an object array.
       int32_t length = h_obj->AsObjectArray<mirror::Object>()->GetLength();
@@ -854,6 +917,14 @@
   }
 }
 
+void ImageWriter::AssignMethodOffset(ArtMethod* method, Bin bin) {
+  auto it = native_object_reloc_.find(method);
+  CHECK(it == native_object_reloc_.end()) << "Method " << method << " already assigned "
+      << PrettyMethod(method);
+  native_object_reloc_.emplace(method, NativeObjectReloc { bin_slot_sizes_[bin], bin });
+  bin_slot_sizes_[bin] += ArtMethod::ObjectSize(target_ptr_size_);
+}
+
 void ImageWriter::WalkFieldsCallback(mirror::Object* obj, void* arg) {
   ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg);
   DCHECK(writer != nullptr);
@@ -879,11 +950,12 @@
 }
 
 void ImageWriter::CalculateNewObjectOffsets() {
-  Thread* self = Thread::Current();
+  Thread* const self = Thread::Current();
   StackHandleScope<1> hs(self);
   Handle<ObjectArray<Object>> image_roots(hs.NewHandle(CreateImageRoots()));
 
-  gc::Heap* heap = Runtime::Current()->GetHeap();
+  auto* runtime = Runtime::Current();
+  auto* heap = runtime->GetHeap();
   DCHECK_EQ(0U, image_end_);
 
   // Leave space for the header, but do not write it yet, we need to
@@ -896,6 +968,21 @@
   PrepareDexCacheArraySlots();
   // Clear any pre-existing monitors which may have been in the monitor words, assign bin slots.
   heap->VisitObjects(WalkFieldsCallback, this);
+  // Write the image runtime methods.
+  image_methods_[ImageHeader::kResolutionMethod] = runtime->GetResolutionMethod();
+  image_methods_[ImageHeader::kImtConflictMethod] = runtime->GetImtConflictMethod();
+  image_methods_[ImageHeader::kImtUnimplementedMethod] = runtime->GetImtUnimplementedMethod();
+  image_methods_[ImageHeader::kCalleeSaveMethod] = runtime->GetCalleeSaveMethod(Runtime::kSaveAll);
+  image_methods_[ImageHeader::kRefsOnlySaveMethod] =
+      runtime->GetCalleeSaveMethod(Runtime::kRefsOnly);
+  image_methods_[ImageHeader::kRefsAndArgsSaveMethod] =
+      runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
+  for (auto* m : image_methods_) {
+    CHECK(m != nullptr);
+    CHECK(m->IsRuntimeMethod());
+    AssignMethodOffset(m, kBinArtMethodDirty);
+  }
+
   // Calculate cumulative bin slot sizes.
   size_t previous_sizes = 0u;
   for (size_t i = 0; i != kBinSize; ++i) {
@@ -913,7 +1000,14 @@
 
   image_roots_address_ = PointerToLowMemUInt32(GetImageAddress(image_roots.Get()));
 
-  // Note that image_end_ is left at end of used mirror space
+  // Update the native relocations by adding their bin sums.
+  for (auto& pair : native_object_reloc_) {
+    auto& native_reloc = pair.second;
+    native_reloc.offset += image_objects_offset_begin_ +
+        bin_slot_previous_sizes_[native_reloc.bin_type];
+  }
+
+  // Note that image_end_ is left at end of used mirror object section.
 }
 
 void ImageWriter::CreateHeader(size_t oat_loaded_size, size_t oat_data_offset) {
@@ -922,47 +1016,87 @@
   const uint8_t* oat_file_end = oat_file_begin + oat_loaded_size;
   oat_data_begin_ = oat_file_begin + oat_data_offset;
   const uint8_t* oat_data_end = oat_data_begin_ + oat_file_->Size();
-  // Write out sections.
-  size_t cur_pos = image_end_;
-  // Add fields.
-  auto fields_offset = cur_pos;
-  CHECK_EQ(image_objects_offset_begin_ + GetBinSizeSum(kBinArtField), fields_offset);
-  auto fields_size = bin_slot_sizes_[kBinArtField];
-  cur_pos += fields_size;
-  // Return to write header at start of image with future location of image_roots. At this point,
-  // image_end_ is the size of the image (excluding bitmaps, ArtFields).
-  /*
-  const size_t heap_bytes_per_bitmap_byte = kBitsPerByte * kObjectAlignment;
-  const size_t bitmap_bytes = RoundUp(image_end_, heap_bytes_per_bitmap_byte) /
-      heap_bytes_per_bitmap_byte;
-      */
+
+  // Create the image sections.
+  ImageSection sections[ImageHeader::kSectionCount];
+  // Objects section
+  auto* objects_section = &sections[ImageHeader::kSectionObjects];
+  *objects_section = ImageSection(0u, image_end_);
+  size_t cur_pos = objects_section->End();
+  // Add field section.
+  auto* field_section = &sections[ImageHeader::kSectionArtFields];
+  *field_section = ImageSection(cur_pos, bin_slot_sizes_[kBinArtField]);
+  CHECK_EQ(image_objects_offset_begin_ + bin_slot_previous_sizes_[kBinArtField],
+           field_section->Offset());
+  cur_pos = field_section->End();
+  // Add method section.
+  auto* methods_section = &sections[ImageHeader::kSectionArtMethods];
+  *methods_section = ImageSection(cur_pos, bin_slot_sizes_[kBinArtMethodClean] +
+                                  bin_slot_sizes_[kBinArtMethodDirty]);
+  CHECK_EQ(image_objects_offset_begin_ + bin_slot_previous_sizes_[kBinArtMethodClean],
+           methods_section->Offset());
+  cur_pos = methods_section->End();
+  // Finally bitmap section.
   const size_t bitmap_bytes = image_bitmap_->Size();
-  auto bitmap_offset = RoundUp(cur_pos, kPageSize);
-  auto bitmap_size = RoundUp(bitmap_bytes, kPageSize);
-  cur_pos += bitmap_size;
-  new (image_->Begin()) ImageHeader(PointerToLowMemUInt32(image_begin_),
-                                    static_cast<uint32_t>(image_end_),
-                                    fields_offset, fields_size,
-                                    bitmap_offset, bitmap_size,
-                                    image_roots_address_,
-                                    oat_file_->GetOatHeader().GetChecksum(),
-                                    PointerToLowMemUInt32(oat_file_begin),
-                                    PointerToLowMemUInt32(oat_data_begin_),
-                                    PointerToLowMemUInt32(oat_data_end),
-                                    PointerToLowMemUInt32(oat_file_end),
-                                    compile_pic_);
+  auto* bitmap_section = &sections[ImageHeader::kSectionImageBitmap];
+  *bitmap_section = ImageSection(RoundUp(cur_pos, kPageSize), RoundUp(bitmap_bytes, kPageSize));
+  cur_pos = bitmap_section->End();
+  if (kIsDebugBuild) {
+    size_t idx = 0;
+    for (auto& section : sections) {
+      LOG(INFO) << static_cast<ImageHeader::ImageSections>(idx) << " " << section;
+      ++idx;
+    }
+    LOG(INFO) << "Methods: clean=" << clean_methods_ << " dirty=" << dirty_methods_;
+  }
+  // Create the header.
+  new (image_->Begin()) ImageHeader(
+      PointerToLowMemUInt32(image_begin_), static_cast<uint32_t>(methods_section->End()), sections,
+      image_roots_address_, oat_file_->GetOatHeader().GetChecksum(),
+      PointerToLowMemUInt32(oat_file_begin), PointerToLowMemUInt32(oat_data_begin_),
+      PointerToLowMemUInt32(oat_data_end), PointerToLowMemUInt32(oat_file_end), target_ptr_size_,
+      compile_pic_);
+}
+
+ArtMethod* ImageWriter::GetImageMethodAddress(ArtMethod* method) {
+  auto it = native_object_reloc_.find(method);
+  CHECK(it != native_object_reloc_.end()) << PrettyMethod(method) << " @ " << method;
+  CHECK_GE(it->second.offset, image_end_) << "ArtMethods should be after Objects";
+  return reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset);
 }
 
 void ImageWriter::CopyAndFixupNativeData() {
-  // Copy ArtFields to their locations and update the array for convenience.
-  auto fields_offset = image_objects_offset_begin_ + GetBinSizeSum(kBinArtField);
-  for (auto& pair : art_field_reloc_) {
-    pair.second += fields_offset;
-    auto* dest = image_->Begin() + pair.second;
-    DCHECK_GE(dest, image_->Begin() + image_end_);
-    memcpy(dest, pair.first, sizeof(ArtField));
-    reinterpret_cast<ArtField*>(dest)->SetDeclaringClass(
-        down_cast<Class*>(GetImageAddress(pair.first->GetDeclaringClass())));
+  // Copy ArtFields and methods to their locations and update the array for convenience.
+  for (auto& pair : native_object_reloc_) {
+    auto& native_reloc = pair.second;
+    if (native_reloc.bin_type == kBinArtField) {
+      auto* dest = image_->Begin() + native_reloc.offset;
+      DCHECK_GE(dest, image_->Begin() + image_end_);
+      memcpy(dest, pair.first, sizeof(ArtField));
+      reinterpret_cast<ArtField*>(dest)->SetDeclaringClass(
+          GetImageAddress(reinterpret_cast<ArtField*>(pair.first)->GetDeclaringClass()));
+    } else {
+      CHECK(IsArtMethodBin(native_reloc.bin_type)) << native_reloc.bin_type;
+      auto* dest = image_->Begin() + native_reloc.offset;
+      DCHECK_GE(dest, image_->Begin() + image_end_);
+      CopyAndFixupMethod(reinterpret_cast<ArtMethod*>(pair.first),
+                         reinterpret_cast<ArtMethod*>(dest));
+    }
+  }
+  // Fixup the image method roots.
+  auto* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
+  const auto& methods_section = image_header->GetMethodsSection();
+  for (size_t i = 0; i < ImageHeader::kImageMethodsCount; ++i) {
+    auto* m = image_methods_[i];
+    CHECK(m != nullptr);
+    auto it = native_object_reloc_.find(m);
+    CHECK(it != native_object_reloc_.end()) << "No fowarding for " << PrettyMethod(m);
+    auto& native_reloc = it->second;
+    CHECK(methods_section.Contains(native_reloc.offset)) << native_reloc.offset << " not in "
+        << methods_section;
+    CHECK(IsArtMethodBin(native_reloc.bin_type)) << native_reloc.bin_type;
+    auto* dest = reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset);
+    image_header->SetImageMethod(static_cast<ImageHeader::ImageMethod>(i), dest);
   }
 }
 
@@ -984,59 +1118,37 @@
   reinterpret_cast<ImageWriter*>(arg)->CopyAndFixupObject(obj);
 }
 
-bool ImageWriter::CopyAndFixupIfDexCacheFieldArray(mirror::Object* dst, mirror::Object* obj,
-                                                   mirror::Class* klass) {
-  if (!klass->IsArrayClass()) {
-    return false;
-  }
-  auto* component_type = klass->GetComponentType();
-  bool is_int_arr = component_type->IsPrimitiveInt();
-  bool is_long_arr = component_type->IsPrimitiveLong();
-  if (!is_int_arr && !is_long_arr) {
-    return false;
-  }
-  auto it = dex_cache_array_indexes_.find(obj);  // Is this a dex cache array?
-  if (it == dex_cache_array_indexes_.end()) {
-    return false;
-  }
-  mirror::Array* arr = obj->AsArray();
-  CHECK_EQ(reinterpret_cast<Object*>(
-      image_->Begin() + it->second.offset_ + image_objects_offset_begin_), dst);
-  dex_cache_array_indexes_.erase(it);
-  // Fixup int pointers for the field array.
-  CHECK(!arr->IsObjectArray());
+void ImageWriter::FixupPointerArray(mirror::Object* dst, mirror::PointerArray* arr,
+                                    mirror::Class* klass, Bin array_type) {
+  CHECK(klass->IsArrayClass());
+  CHECK(arr->IsIntArray() || arr->IsLongArray()) << PrettyClass(klass) << " " << arr;
+  // Fixup int and long pointers for the ArtMethod or ArtField arrays.
   const size_t num_elements = arr->GetLength();
-  if (target_ptr_size_ == 4u) {
-    // Will get fixed up by fixup object.
-    dst->SetClass<kVerifyNone>(down_cast<mirror::Class*>(
-    GetImageAddress(mirror::IntArray::GetArrayClass())));
-  } else {
-    DCHECK_EQ(target_ptr_size_, 8u);
-    dst->SetClass<kVerifyNone>(down_cast<mirror::Class*>(
-    GetImageAddress(mirror::LongArray::GetArrayClass())));
-  }
-  mirror::Array* dest_array = down_cast<mirror::Array*>(dst);
-  dest_array->SetLength(num_elements);
+  dst->SetClass(GetImageAddress(arr->GetClass()));
+  auto* dest_array = down_cast<mirror::PointerArray*>(dst);
   for (size_t i = 0, count = num_elements; i < count; ++i) {
-    ArtField* field = reinterpret_cast<ArtField*>(is_int_arr ?
-        arr->AsIntArray()->GetWithoutChecks(i) : arr->AsLongArray()->GetWithoutChecks(i));
-    uint8_t* fixup_location = nullptr;
-    if (field != nullptr) {
-      auto it2 = art_field_reloc_.find(field);
-      CHECK(it2 != art_field_reloc_.end()) << "No relocation for field " << PrettyField(field);
-      fixup_location = image_begin_ + it2->second;
+    auto* elem = arr->GetElementPtrSize<void*>(i, target_ptr_size_);
+    if (elem != nullptr) {
+      auto it = native_object_reloc_.find(elem);
+      if (it == native_object_reloc_.end()) {
+        if (IsArtMethodBin(array_type)) {
+          auto* method = reinterpret_cast<ArtMethod*>(elem);
+          LOG(FATAL) << "No relocation entry for ArtMethod " << PrettyMethod(method) << " @ "
+              << method << " idx=" << i << "/" << num_elements << " with declaring class "
+              << PrettyClass(method->GetDeclaringClass());
+        } else {
+          CHECK_EQ(array_type, kBinArtField);
+          auto* field = reinterpret_cast<ArtField*>(elem);
+          LOG(FATAL) << "No relocation entry for ArtField " << PrettyField(field) << " @ "
+              << field << " idx=" << i << "/" << num_elements << " with declaring class "
+              << PrettyClass(field->GetDeclaringClass());
+        }
+      } else {
+        elem = image_begin_ + it->second.offset;
+      }
     }
-    if (target_ptr_size_ == 4u) {
-      down_cast<mirror::IntArray*>(dest_array)->SetWithoutChecks<false, false, kVerifyNone>(
-          i, static_cast<uint32_t>(reinterpret_cast<uint64_t>(fixup_location)));
-    } else {
-      DCHECK_EQ(target_ptr_size_, 8u);
-      down_cast<mirror::LongArray*>(dest_array)->SetWithoutChecks<false, false, kVerifyNone>(
-          i, reinterpret_cast<uint64_t>(fixup_location));
-    }
+    dest_array->SetElementPtrSize<false, true>(i, elem, target_ptr_size_);
   }
-  dst->SetLockWord<kVerifyNone>(LockWord::Default(), false);
-  return true;
 }
 
 void ImageWriter::CopyAndFixupObject(Object* obj) {
@@ -1044,19 +1156,8 @@
   size_t offset = GetImageOffset(obj);
   auto* dst = reinterpret_cast<Object*>(image_->Begin() + offset);
   const uint8_t* src = reinterpret_cast<const uint8_t*>(obj);
-  size_t n;
-  mirror::Class* klass = obj->GetClass();
 
-  if (CopyAndFixupIfDexCacheFieldArray(dst, obj, klass)) {
-    return;
-  }
-  if (klass->IsArtMethodClass()) {
-    // Size without pointer fields since we don't want to overrun the buffer if target art method
-    // is 32 bits but source is 64 bits.
-    n = mirror::ArtMethod::SizeWithoutPointerFields(target_ptr_size_);
-  } else {
-    n = obj->SizeOf();
-  }
+  size_t n = obj->SizeOf();
   DCHECK_LE(offset + n, image_->Size());
   memcpy(dst, src, n);
 
@@ -1115,23 +1216,51 @@
 
 void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) {
   // Copy and fix up ArtFields in the class.
-  ArtField* fields[2] = { orig->AsClass()->GetSFields(), orig->AsClass()->GetIFields() };
-  size_t num_fields[2] = { orig->AsClass()->NumStaticFields(),
-      orig->AsClass()->NumInstanceFields() };
-  // Update the arrays.
+  ArtField* fields[2] = { orig->GetSFields(), orig->GetIFields() };
+  size_t num_fields[2] = { orig->NumStaticFields(), orig->NumInstanceFields() };
+  // Update the field arrays.
   for (size_t i = 0; i < 2; ++i) {
     if (num_fields[i] == 0) {
       CHECK(fields[i] == nullptr);
       continue;
     }
-    auto it = art_field_reloc_.find(fields[i]);
-    CHECK(it != art_field_reloc_.end()) << PrettyClass(orig->AsClass()) << " : "
-        << PrettyField(fields[i]);
-    auto* image_fields = reinterpret_cast<ArtField*>(image_begin_ + it->second);
+    auto it = native_object_reloc_.find(fields[i]);
+    CHECK(it != native_object_reloc_.end()) << PrettyClass(orig) << " : " << PrettyField(fields[i]);
+    auto* image_fields = reinterpret_cast<ArtField*>(image_begin_ + it->second.offset);
     if (i == 0) {
-      down_cast<Class*>(copy)->SetSFieldsUnchecked(image_fields);
+      copy->SetSFieldsUnchecked(image_fields);
     } else {
-      down_cast<Class*>(copy)->SetIFieldsUnchecked(image_fields);
+      copy->SetIFieldsUnchecked(image_fields);
+    }
+  }
+  // Update direct / virtual method arrays.
+  auto* direct_methods = orig->GetDirectMethodsPtr();
+  if (direct_methods != nullptr) {
+    auto it = native_object_reloc_.find(direct_methods);
+    CHECK(it != native_object_reloc_.end()) << PrettyClass(orig);
+    copy->SetDirectMethodsPtrUnchecked(
+        reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset));
+  }
+  auto* virtual_methods = orig->GetVirtualMethodsPtr();
+  if (virtual_methods != nullptr) {
+    auto it = native_object_reloc_.find(virtual_methods);
+    CHECK(it != native_object_reloc_.end()) << PrettyClass(orig);
+    copy->SetVirtualMethodsPtr(
+        reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset));
+  }
+  // Fix up embedded tables.
+  if (orig->ShouldHaveEmbeddedImtAndVTable()) {
+    for (int32_t i = 0; i < orig->GetEmbeddedVTableLength(); ++i) {
+      auto it = native_object_reloc_.find(orig->GetEmbeddedVTableEntry(i, target_ptr_size_));
+      CHECK(it != native_object_reloc_.end()) << PrettyClass(orig);
+      copy->SetEmbeddedVTableEntryUnchecked(
+          i, reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset), target_ptr_size_);
+    }
+    for (size_t i = 0; i < mirror::Class::kImtSize; ++i) {
+      auto it = native_object_reloc_.find(orig->GetEmbeddedImTableEntry(i, target_ptr_size_));
+      CHECK(it != native_object_reloc_.end()) << PrettyClass(orig);
+      copy->SetEmbeddedImTableEntry(
+          i, reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset), target_ptr_size_);
     }
   }
   FixupClassVisitor visitor(this, copy);
@@ -1149,18 +1278,39 @@
       DCHECK_EQ(copy->GetReadBarrierPointer(), GetImageAddress(orig));
     }
   }
+  auto* klass = orig->GetClass();
+  if (klass->IsIntArrayClass() || klass->IsLongArrayClass()) {
+    // Is this a native dex cache array?
+    auto it = pointer_arrays_.find(down_cast<mirror::PointerArray*>(orig));
+    if (it != pointer_arrays_.end()) {
+      // Should only need to fixup every pointer array exactly once.
+      FixupPointerArray(copy, down_cast<mirror::PointerArray*>(orig), klass, it->second);
+      pointer_arrays_.erase(it);
+      return;
+    }
+    CHECK(dex_cache_array_indexes_.find(orig) == dex_cache_array_indexes_.end())
+        << "Should have been pointer array.";
+  }
   if (orig->IsClass()) {
     FixupClass(orig->AsClass<kVerifyNone>(), down_cast<mirror::Class*>(copy));
   } else {
+    if (klass == mirror::Method::StaticClass() || klass == mirror::Constructor::StaticClass()) {
+      // Need to go update the ArtMethod.
+      auto* dest = down_cast<mirror::AbstractMethod*>(copy);
+      auto* src = down_cast<mirror::AbstractMethod*>(orig);
+      ArtMethod* src_method = src->GetArtMethod();
+      auto it = native_object_reloc_.find(src_method);
+      CHECK(it != native_object_reloc_.end()) << "Missing relocation for AbstractMethod.artMethod "
+          << PrettyMethod(src_method);
+      dest->SetArtMethod(
+          reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset));
+    }
     FixupVisitor visitor(this, copy);
     orig->VisitReferences<true /*visit class*/>(visitor, visitor);
   }
-  if (orig->IsArtMethod<kVerifyNone>()) {
-    FixupMethod(orig->AsArtMethod<kVerifyNone>(), down_cast<ArtMethod*>(copy));
-  }
 }
 
-const uint8_t* ImageWriter::GetQuickCode(mirror::ArtMethod* method, bool* quick_is_interpreted) {
+const uint8_t* ImageWriter::GetQuickCode(ArtMethod* method, bool* quick_is_interpreted) {
   DCHECK(!method->IsResolutionMethod() && !method->IsImtConflictMethod() &&
          !method->IsImtUnimplementedMethod() && !method->IsAbstract()) << PrettyMethod(method);
 
@@ -1172,27 +1322,31 @@
       method->GetEntryPointFromQuickCompiledCodePtrSize(target_ptr_size_));
   const uint8_t* quick_code = GetOatAddress(quick_oat_code_offset);
   *quick_is_interpreted = false;
-  if (quick_code != nullptr &&
-      (!method->IsStatic() || method->IsConstructor() || method->GetDeclaringClass()->IsInitialized())) {
+  if (quick_code != nullptr && (!method->IsStatic() || method->IsConstructor() ||
+      method->GetDeclaringClass()->IsInitialized())) {
     // We have code for a non-static or initialized method, just use the code.
+    DCHECK_GE(quick_code, oat_data_begin_);
   } else if (quick_code == nullptr && method->IsNative() &&
       (!method->IsStatic() || method->GetDeclaringClass()->IsInitialized())) {
     // Non-static or initialized native method missing compiled code, use generic JNI version.
     quick_code = GetOatAddress(quick_generic_jni_trampoline_offset_);
+    DCHECK_GE(quick_code, oat_data_begin_);
   } else if (quick_code == nullptr && !method->IsNative()) {
     // We don't have code at all for a non-native method, use the interpreter.
     quick_code = GetOatAddress(quick_to_interpreter_bridge_offset_);
     *quick_is_interpreted = true;
+    DCHECK_GE(quick_code, oat_data_begin_);
   } else {
     CHECK(!method->GetDeclaringClass()->IsInitialized());
     // We have code for a static method, but need to go through the resolution stub for class
     // initialization.
     quick_code = GetOatAddress(quick_resolution_trampoline_offset_);
+    DCHECK_GE(quick_code, oat_data_begin_);
   }
   return quick_code;
 }
 
-const uint8_t* ImageWriter::GetQuickEntryPoint(mirror::ArtMethod* method) {
+const uint8_t* ImageWriter::GetQuickEntryPoint(ArtMethod* method) {
   // Calculate the quick entry point following the same logic as FixupMethod() below.
   // The resolution method has a special trampoline to call.
   Runtime* runtime = Runtime::Current();
@@ -1214,50 +1368,57 @@
   }
 }
 
-void ImageWriter::FixupMethod(ArtMethod* orig, ArtMethod* copy) {
+void ImageWriter::CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy) {
+  memcpy(copy, orig, ArtMethod::ObjectSize(target_ptr_size_));
+
+  copy->SetDeclaringClass(GetImageAddress(orig->GetDeclaringClassUnchecked()));
+  copy->SetDexCacheResolvedMethods(GetImageAddress(orig->GetDexCacheResolvedMethods()));
+  copy->SetDexCacheResolvedTypes(GetImageAddress(orig->GetDexCacheResolvedTypes()));
+
   // OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to
   // oat_begin_
-  // For 64 bit targets we need to repack the current runtime pointer sized fields to the right
-  // locations.
-  // Copy all of the fields from the runtime methods to the target methods first since we did a
-  // bytewise copy earlier.
-  copy->SetEntryPointFromInterpreterPtrSize<kVerifyNone>(
-      orig->GetEntryPointFromInterpreterPtrSize(target_ptr_size_), target_ptr_size_);
-  copy->SetEntryPointFromJniPtrSize<kVerifyNone>(
-      orig->GetEntryPointFromJniPtrSize(target_ptr_size_), target_ptr_size_);
-  copy->SetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(
-      orig->GetEntryPointFromQuickCompiledCodePtrSize(target_ptr_size_), target_ptr_size_);
 
   // The resolution method has a special trampoline to call.
   Runtime* runtime = Runtime::Current();
   if (UNLIKELY(orig == runtime->GetResolutionMethod())) {
-    copy->SetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(
+    copy->SetEntryPointFromQuickCompiledCodePtrSize(
         GetOatAddress(quick_resolution_trampoline_offset_), target_ptr_size_);
   } else if (UNLIKELY(orig == runtime->GetImtConflictMethod() ||
                       orig == runtime->GetImtUnimplementedMethod())) {
-    copy->SetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(
+    copy->SetEntryPointFromQuickCompiledCodePtrSize(
         GetOatAddress(quick_imt_conflict_trampoline_offset_), target_ptr_size_);
+  } else if (UNLIKELY(orig->IsRuntimeMethod())) {
+    bool found_one = false;
+    for (size_t i = 0; i < static_cast<size_t>(Runtime::kLastCalleeSaveType); ++i) {
+      auto idx = static_cast<Runtime::CalleeSaveType>(i);
+      if (runtime->HasCalleeSaveMethod(idx) && runtime->GetCalleeSaveMethod(idx) == orig) {
+        found_one = true;
+        break;
+      }
+    }
+    CHECK(found_one) << "Expected to find callee save method but got " << PrettyMethod(orig);
+    CHECK(copy->IsRuntimeMethod());
   } else {
     // We assume all methods have code. If they don't currently then we set them to the use the
     // resolution trampoline. Abstract methods never have code and so we need to make sure their
     // use results in an AbstractMethodError. We use the interpreter to achieve this.
     if (UNLIKELY(orig->IsAbstract())) {
-      copy->SetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(
+      copy->SetEntryPointFromQuickCompiledCodePtrSize(
           GetOatAddress(quick_to_interpreter_bridge_offset_), target_ptr_size_);
-      copy->SetEntryPointFromInterpreterPtrSize<kVerifyNone>(
+      copy->SetEntryPointFromInterpreterPtrSize(
           reinterpret_cast<EntryPointFromInterpreter*>(const_cast<uint8_t*>(
                   GetOatAddress(interpreter_to_interpreter_bridge_offset_))), target_ptr_size_);
     } else {
       bool quick_is_interpreted;
       const uint8_t* quick_code = GetQuickCode(orig, &quick_is_interpreted);
-      copy->SetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(quick_code, target_ptr_size_);
+      copy->SetEntryPointFromQuickCompiledCodePtrSize(quick_code, target_ptr_size_);
 
       // JNI entrypoint:
       if (orig->IsNative()) {
         // The native method's pointer is set to a stub to lookup via dlsym.
         // Note this is not the code_ pointer, that is handled above.
-        copy->SetEntryPointFromJniPtrSize<kVerifyNone>(GetOatAddress(jni_dlsym_lookup_offset_),
-                                                       target_ptr_size_);
+        copy->SetEntryPointFromJniPtrSize(
+            GetOatAddress(jni_dlsym_lookup_offset_), target_ptr_size_);
       }
 
       // Interpreter entrypoint:
@@ -1268,8 +1429,7 @@
       EntryPointFromInterpreter* interpreter_entrypoint =
           reinterpret_cast<EntryPointFromInterpreter*>(
               const_cast<uint8_t*>(GetOatAddress(interpreter_code)));
-      copy->SetEntryPointFromInterpreterPtrSize<kVerifyNone>(
-          interpreter_entrypoint, target_ptr_size_);
+      copy->SetEntryPointFromInterpreterPtrSize(interpreter_entrypoint, target_ptr_size_);
     }
   }
 }
@@ -1306,8 +1466,8 @@
 
 ImageWriter::BinSlot::BinSlot(uint32_t lockword) : lockword_(lockword) {
   // These values may need to get updated if more bins are added to the enum Bin
-  static_assert(kBinBits == 4, "wrong number of bin bits");
-  static_assert(kBinShift == 28, "wrong number of shift");
+  static_assert(kBinBits == 3, "wrong number of bin bits");
+  static_assert(kBinShift == 27, "wrong number of shift");
   static_assert(sizeof(BinSlot) == sizeof(LockWord), "BinSlot/LockWord must have equal sizes");
 
   DCHECK_LT(GetBin(), kBinSize);
@@ -1327,13 +1487,4 @@
   return lockword_ & ~kBinMask;
 }
 
-void ImageWriter::FreeStringDataArray() {
-  if (string_data_array_ != nullptr) {
-    gc::space::LargeObjectSpace* los = Runtime::Current()->GetHeap()->GetLargeObjectsSpace();
-    if (los != nullptr) {
-      los->Free(Thread::Current(), reinterpret_cast<mirror::Object*>(string_data_array_));
-    }
-  }
-}
-
 }  // namespace art
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index 5921732..a35d6ad 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -30,12 +30,13 @@
 #include "base/macros.h"
 #include "driver/compiler_driver.h"
 #include "gc/space/space.h"
+#include "lock_word.h"
 #include "mem_map.h"
 #include "oat_file.h"
 #include "mirror/dex_cache.h"
 #include "os.h"
 #include "safe_map.h"
-#include "gc/space/space.h"
+#include "utils.h"
 
 namespace art {
 
@@ -53,18 +54,12 @@
         quick_to_interpreter_bridge_offset_(0), compile_pic_(compile_pic),
         target_ptr_size_(InstructionSetPointerSize(compiler_driver_.GetInstructionSet())),
         bin_slot_sizes_(), bin_slot_previous_sizes_(), bin_slot_count_(),
-        string_data_array_(nullptr) {
+        dirty_methods_(0u), clean_methods_(0u) {
     CHECK_NE(image_begin, 0U);
+    std::fill(image_methods_, image_methods_ + arraysize(image_methods_), nullptr);
   }
 
   ~ImageWriter() {
-    // For interned strings a large array is allocated to hold all the character data and avoid
-    // overhead. However, no GC is run anymore at this point. As the array is likely large, it
-    // will be allocated in the large object space, where valgrind can track every single
-    // allocation. Not explicitly freeing that array will be recognized as a leak.
-    if (RUNNING_ON_VALGRIND != 0) {
-      FreeStringDataArray();
-    }
   }
 
   bool PrepareImageAddressSpace();
@@ -73,14 +68,14 @@
     return image_roots_address_ != 0u;
   }
 
-  mirror::Object* GetImageAddress(mirror::Object* object) const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    if (object == nullptr) {
-      return nullptr;
-    }
-    return reinterpret_cast<mirror::Object*>(image_begin_ + GetImageOffset(object));
+  template <typename T>
+  T* GetImageAddress(T* object) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return object == nullptr ? nullptr :
+        reinterpret_cast<T*>(image_begin_ + GetImageOffset(object));
   }
 
+  ArtMethod* GetImageMethodAddress(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   mirror::HeapReference<mirror::Object>* GetDexCacheArrayElementImageAddress(
       const DexFile* dex_file, uint32_t offset) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     auto it = dex_cache_array_starts_.find(dex_file);
@@ -90,11 +85,12 @@
   }
 
   uint8_t* GetOatFileBegin() const {
-    return image_begin_ + RoundUp(image_end_ + bin_slot_sizes_[kBinArtField], kPageSize);
+    return image_begin_ + RoundUp(
+        image_end_ + bin_slot_sizes_[kBinArtField] + bin_slot_sizes_[kBinArtMethodDirty] +
+        bin_slot_sizes_[kBinArtMethodClean], kPageSize);
   }
 
-  bool Write(const std::string& image_filename,
-             const std::string& oat_filename,
+  bool Write(const std::string& image_filename, const std::string& oat_filename,
              const std::string& oat_location)
       LOCKS_EXCLUDED(Locks::mutator_lock_);
 
@@ -124,11 +120,15 @@
     kBinClassInitializedFinalStatics,  // Class initializers have been run, no non-final statics
     kBinClassInitialized,         // Class initializers have been run
     kBinClassVerified,            // Class verified, but initializers haven't been run
-    kBinArtMethodNative,          // Art method that is actually native
-    kBinArtMethodNotInitialized,  // Art method with a declaring class that wasn't initialized
     // Add more bins here if we add more segregation code.
-    // Non mirror fields must be below. ArtFields should be always clean.
+    // Non mirror fields must be below.
+    // ArtFields should be always clean.
     kBinArtField,
+    // If the class is initialized, then the ArtMethods are probably clean.
+    kBinArtMethodClean,
+    // ArtMethods may be dirty if the class has native methods or a declaring class that isn't
+    // initialized.
+    kBinArtMethodDirty,
     kBinSize,
     // Number of bins which are for mirror objects.
     kBinMirrorCount = kBinArtField,
@@ -138,9 +138,12 @@
 
   static constexpr size_t kBinBits = MinimumBitsToStore<uint32_t>(kBinMirrorCount - 1);
   // uint32 = typeof(lockword_)
-  static constexpr size_t kBinShift = BitSizeOf<uint32_t>() - kBinBits;
+  // Subtract read barrier bits since we want these to remain 0, or else it may result in DCHECK
+  // failures due to invalid read barrier bits during object field reads.
+  static const size_t kBinShift = BitSizeOf<uint32_t>() - kBinBits -
+      LockWord::kReadBarrierStateSize;
   // 111000.....0
-  static constexpr size_t kBinMask = ((static_cast<size_t>(1) << kBinBits) - 1) << kBinShift;
+  static const size_t kBinMask = ((static_cast<size_t>(1) << kBinBits) - 1) << kBinShift;
 
   // We use the lock word to store the bin # and bin index of the object in the image.
   //
@@ -172,6 +175,8 @@
   bool IsImageOffsetAssigned(mirror::Object* object) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   size_t GetImageOffset(mirror::Object* object) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void UpdateImageOffset(mirror::Object* obj, uintptr_t offset)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void PrepareDexCacheArraySlots() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void AssignImageBinSlot(mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -181,6 +186,8 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   BinSlot GetImageBinSlot(mirror::Object* object) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  void AddMethodPointerArray(mirror::PointerArray* arr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   static void* GetImageAddressCallback(void* writer, mirror::Object* obj)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return reinterpret_cast<ImageWriter*>(writer)->GetImageAddress(obj);
@@ -197,10 +204,12 @@
     // With Quick, code is within the OatFile, as there are all in one
     // .o ELF object.
     DCHECK_LT(offset, oat_file_->Size());
-    if (offset == 0u) {
-      return nullptr;
-    }
-    return oat_data_begin_ + offset;
+    DCHECK(oat_data_begin_ != nullptr);
+    return offset == 0u ? nullptr : oat_data_begin_ + offset;
+  }
+
+  static bool IsArtMethodBin(Bin bin) {
+    return bin == kBinArtMethodClean || bin == kBinArtMethodDirty;
   }
 
   // Returns true if the class was in the original requested image classes list.
@@ -257,21 +266,20 @@
   static void CopyAndFixupObjectsCallback(mirror::Object* obj, void* arg)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void CopyAndFixupObject(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool CopyAndFixupIfDexCacheFieldArray(mirror::Object* dst, mirror::Object* obj,
-                                        mirror::Class* klass)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void FixupMethod(mirror::ArtMethod* orig, mirror::ArtMethod* copy)
+  void CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FixupClass(mirror::Class* orig, mirror::Class* copy)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FixupObject(mirror::Object* orig, mirror::Object* copy)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void FixupPointerArray(mirror::Object* dst, mirror::PointerArray* arr, mirror::Class* klass,
+                         Bin array_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get quick code for non-resolution/imt_conflict/abstract method.
-  const uint8_t* GetQuickCode(mirror::ArtMethod* method, bool* quick_is_interpreted)
+  const uint8_t* GetQuickCode(ArtMethod* method, bool* quick_is_interpreted)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  const uint8_t* GetQuickEntryPoint(mirror::ArtMethod* method)
+  const uint8_t* GetQuickEntryPoint(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Patches references in OatFile to expect runtime addresses.
@@ -280,8 +288,11 @@
   // Calculate the sum total of the bin slot sizes in [0, up_to). Defaults to all bins.
   size_t GetBinSizeSum(Bin up_to = kBinSize) const;
 
-  // Release the string_data_array_.
-  void FreeStringDataArray();
+  // Return true if a method is likely to be dirtied at runtime.
+  bool WillMethodBeDirty(ArtMethod* m) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Assign the offset for an ArtMethod.
+  void AssignMethodOffset(ArtMethod* method, Bin bin) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   const CompilerDriver& compiler_driver_;
 
@@ -308,9 +319,14 @@
   struct DexCacheArrayLocation {
     size_t offset_;
     size_t length_;
+    Bin bin_type_;
   };
   SafeMap<mirror::Object*, DexCacheArrayLocation> dex_cache_array_indexes_;
 
+  // Pointer arrays that need to be updated. Since these are only some int and long arrays, we need
+  // to keep track. These include vtable arrays, iftable arrays, and dex caches.
+  std::unordered_map<mirror::PointerArray*, Bin> pointer_arrays_;
+
   // The start offsets of the dex cache arrays.
   SafeMap<const DexFile*, size_t> dex_cache_array_starts_;
 
@@ -344,12 +360,21 @@
   size_t bin_slot_previous_sizes_[kBinSize];  // Number of bytes in previous bins.
   size_t bin_slot_count_[kBinSize];  // Number of objects in a bin
 
-  // ArtField relocating map, ArtFields are allocated as array of structs but we want to have one
-  // entry per art field for convenience.
-  // ArtFields are placed right after the end of the image objects (aka sum of bin_slot_sizes_).
-  std::unordered_map<ArtField*, uintptr_t> art_field_reloc_;
+  // ArtField, ArtMethod relocating map. These are allocated as array of structs but we want to
+  // have one entry per art field for convenience. ArtFields are placed right after the end of the
+  // image objects (aka sum of bin_slot_sizes_). ArtMethods are placed right after the ArtFields.
+  struct NativeObjectReloc {
+    uintptr_t offset;
+    Bin bin_type;
+  };
+  std::unordered_map<void*, NativeObjectReloc> native_object_reloc_;
 
-  void* string_data_array_;  // The backing for the interned strings.
+  // Runtime ArtMethods which aren't reachable from any Class but need to be copied into the image.
+  ArtMethod* image_methods_[ImageHeader::kImageMethodsCount];
+
+  // Counters for measurements, used for logging only.
+  uint64_t dirty_methods_;
+  uint64_t clean_methods_;
 
   friend class FixupVisitor;
   friend class FixupClassVisitor;
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index e28f8f0..d0a926f 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -16,6 +16,7 @@
 
 #include "jit_compiler.h"
 
+#include "art_method-inl.h"
 #include "arch/instruction_set.h"
 #include "arch/instruction_set_features.h"
 #include "base/time_utils.h"
@@ -27,7 +28,6 @@
 #include "driver/compiler_options.h"
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
-#include "mirror/art_method-inl.h"
 #include "oat_file-inl.h"
 #include "object_lock.h"
 #include "thread_list.h"
@@ -54,7 +54,7 @@
   delete reinterpret_cast<JitCompiler*>(handle);
 }
 
-extern "C" bool jit_compile_method(void* handle, mirror::ArtMethod* method, Thread* self)
+extern "C" bool jit_compile_method(void* handle, ArtMethod* method, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   auto* jit_compiler = reinterpret_cast<JitCompiler*>(handle);
   DCHECK(jit_compiler != nullptr);
@@ -104,34 +104,33 @@
 JitCompiler::~JitCompiler() {
 }
 
-bool JitCompiler::CompileMethod(Thread* self, mirror::ArtMethod* method) {
+bool JitCompiler::CompileMethod(Thread* self, ArtMethod* method) {
   TimingLogger logger("JIT compiler timing logger", true, VLOG_IS_ON(jit));
   const uint64_t start_time = NanoTime();
   StackHandleScope<2> hs(self);
   self->AssertNoPendingException();
   Runtime* runtime = Runtime::Current();
-  Handle<mirror::ArtMethod> h_method(hs.NewHandle(method));
   if (runtime->GetJit()->GetCodeCache()->ContainsMethod(method)) {
     VLOG(jit) << "Already compiled " << PrettyMethod(method);
     return true;  // Already compiled
   }
-  Handle<mirror::Class> h_class(hs.NewHandle(h_method->GetDeclaringClass()));
+  Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
   {
     TimingLogger::ScopedTiming t2("Initializing", &logger);
     if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
-      VLOG(jit) << "JIT failed to initialize " << PrettyMethod(h_method.Get());
+      VLOG(jit) << "JIT failed to initialize " << PrettyMethod(method);
       return false;
     }
   }
   const DexFile* dex_file = h_class->GetDexCache()->GetDexFile();
-  MethodReference method_ref(dex_file, h_method->GetDexMethodIndex());
+  MethodReference method_ref(dex_file, method->GetDexMethodIndex());
   // Only verify if we don't already have verification results.
   if (verification_results_->GetVerifiedMethod(method_ref) == nullptr) {
     TimingLogger::ScopedTiming t2("Verifying", &logger);
     std::string error;
-    if (verifier::MethodVerifier::VerifyMethod(h_method.Get(), true, &error) ==
+    if (verifier::MethodVerifier::VerifyMethod(method, true, &error) ==
         verifier::MethodVerifier::kHardFailure) {
-      VLOG(jit) << "Not compile method " << PrettyMethod(h_method.Get())
+      VLOG(jit) << "Not compile method " << PrettyMethod(method)
           << " due to verification failure " << error;
       return false;
     }
@@ -139,7 +138,7 @@
   CompiledMethod* compiled_method = nullptr;
   {
     TimingLogger::ScopedTiming t2("Compiling", &logger);
-    compiled_method = compiler_driver_->CompileMethod(self, h_method.Get());
+    compiled_method = compiler_driver_->CompileMethod(self, method);
   }
   {
     TimingLogger::ScopedTiming t2("TrimMaps", &logger);
@@ -153,16 +152,15 @@
   // Don't add the method if we are supposed to be deoptimized.
   bool result = false;
   if (!runtime->GetInstrumentation()->AreAllMethodsDeoptimized()) {
-    const void* code = runtime->GetClassLinker()->GetOatMethodQuickCodeFor(
-        h_method.Get());
+    const void* code = runtime->GetClassLinker()->GetOatMethodQuickCodeFor(method);
     if (code != nullptr) {
       // Already have some compiled code, just use this instead of linking.
       // TODO: Fix recompilation.
-      h_method->SetEntryPointFromQuickCompiledCode(code);
+      method->SetEntryPointFromQuickCompiledCode(code);
       result = true;
     } else {
       TimingLogger::ScopedTiming t2("MakeExecutable", &logger);
-      result = MakeExecutable(compiled_method, h_method.Get());
+      result = MakeExecutable(compiled_method, method);
     }
   }
   // Remove the compiled method to save memory.
@@ -204,7 +202,7 @@
   return code_ptr;
 }
 
-bool JitCompiler::AddToCodeCache(mirror::ArtMethod* method, const CompiledMethod* compiled_method,
+bool JitCompiler::AddToCodeCache(ArtMethod* method, const CompiledMethod* compiled_method,
                                  OatFile::OatMethod* out_method) {
   Runtime* runtime = Runtime::Current();
   JitCodeCache* const code_cache = runtime->GetJit()->GetCodeCache();
@@ -260,7 +258,7 @@
   return true;
 }
 
-bool JitCompiler::MakeExecutable(CompiledMethod* compiled_method, mirror::ArtMethod* method) {
+bool JitCompiler::MakeExecutable(CompiledMethod* compiled_method, ArtMethod* method) {
   CHECK(method != nullptr);
   CHECK(compiled_method != nullptr);
   OatFile::OatMethod oat_method(nullptr, 0);
diff --git a/compiler/jit/jit_compiler.h b/compiler/jit/jit_compiler.h
index d9a5ac6..b0010e0 100644
--- a/compiler/jit/jit_compiler.h
+++ b/compiler/jit/jit_compiler.h
@@ -28,11 +28,8 @@
 
 namespace art {
 
-class InstructionSetFeatures;
-
-namespace mirror {
 class ArtMethod;
-}
+class InstructionSetFeatures;
 
 namespace jit {
 
@@ -40,11 +37,11 @@
  public:
   static JitCompiler* Create();
   virtual ~JitCompiler();
-  bool CompileMethod(Thread* self, mirror::ArtMethod* method)
+  bool CompileMethod(Thread* self, ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   // This is in the compiler since the runtime doesn't have access to the compiled method
   // structures.
-  bool AddToCodeCache(mirror::ArtMethod* method, const CompiledMethod* compiled_method,
+  bool AddToCodeCache(ArtMethod* method, const CompiledMethod* compiled_method,
                       OatFile::OatMethod* out_method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   CompilerCallbacks* GetCompilerCallbacks() const;
   size_t GetTotalCompileTime() const {
@@ -65,7 +62,7 @@
   uint8_t* WriteMethodHeaderAndCode(
       const CompiledMethod* compiled_method, uint8_t* reserve_begin, uint8_t* reserve_end,
       const uint8_t* mapping_table, const uint8_t* vmap_table, const uint8_t* gc_map);
-  bool MakeExecutable(CompiledMethod* compiled_method, mirror::ArtMethod* method)
+  bool MakeExecutable(CompiledMethod* compiled_method, ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   DISALLOW_COPY_AND_ASSIGN(JitCompiler);
diff --git a/compiler/jni/jni_cfi_test_expected.inc b/compiler/jni/jni_cfi_test_expected.inc
index 42fc30f..dd4496f 100644
--- a/compiler/jni/jni_cfi_test_expected.inc
+++ b/compiler/jni/jni_cfi_test_expected.inc
@@ -84,9 +84,9 @@
     0xFF, 0x03, 0x03, 0xD1, 0xF3, 0x53, 0x06, 0xA9, 0xF5, 0x5B, 0x07, 0xA9,
     0xF7, 0x63, 0x08, 0xA9, 0xF9, 0x6B, 0x09, 0xA9, 0xFB, 0x73, 0x0A, 0xA9,
     0xFD, 0x7B, 0x0B, 0xA9, 0xE8, 0x27, 0x02, 0x6D, 0xEA, 0x2F, 0x03, 0x6D,
-    0xEC, 0x37, 0x04, 0x6D, 0xEE, 0x3F, 0x05, 0x6D, 0xE0, 0x03, 0x00, 0xB9,
-    0xE1, 0xC7, 0x00, 0xB9, 0xE0, 0xCB, 0x00, 0xBD, 0xE2, 0xCF, 0x00, 0xB9,
-    0xE3, 0xD3, 0x00, 0xB9, 0xFF, 0x83, 0x00, 0xD1, 0xFF, 0x83, 0x00, 0x91,
+    0xEC, 0x37, 0x04, 0x6D, 0xEE, 0x3F, 0x05, 0x6D, 0xE0, 0x03, 0x00, 0xF9,
+    0xE1, 0xCB, 0x00, 0xB9, 0xE0, 0xCF, 0x00, 0xBD, 0xE2, 0xD3, 0x00, 0xB9,
+    0xE3, 0xD7, 0x00, 0xB9, 0xFF, 0x83, 0x00, 0xD1, 0xFF, 0x83, 0x00, 0x91,
     0xF3, 0x53, 0x46, 0xA9, 0xF5, 0x5B, 0x47, 0xA9, 0xF7, 0x63, 0x48, 0xA9,
     0xF9, 0x6B, 0x49, 0xA9, 0xFB, 0x73, 0x4A, 0xA9, 0xFD, 0x7B, 0x4B, 0xA9,
     0xE8, 0x27, 0x42, 0x6D, 0xEA, 0x2F, 0x43, 0x6D, 0xEC, 0x37, 0x44, 0x6D,
@@ -106,7 +106,7 @@
 };
 // 0x00000000: sub sp, sp, #0xc0 (192)
 // 0x00000004: .cfi_def_cfa_offset: 192
-// 0x00000004: stp x19, x20, [sp, #96]
+// 0x00000004: stp tr, x20, [sp, #96]
 // 0x00000008: .cfi_offset: r19 at cfa-96
 // 0x00000008: .cfi_offset: r20 at cfa-88
 // 0x00000008: stp x21, x22, [sp, #112]
@@ -136,17 +136,17 @@
 // 0x00000028: stp d14, d15, [sp, #80]
 // 0x0000002c: .cfi_offset_extended: r78 at cfa-112
 // 0x0000002c: .cfi_offset_extended: r79 at cfa-104
-// 0x0000002c: str w0, [sp]
-// 0x00000030: str w1, [sp, #196]
-// 0x00000034: str s0, [sp, #200]
-// 0x00000038: str w2, [sp, #204]
-// 0x0000003c: str w3, [sp, #208]
+// 0x0000002c: str x0, [sp]
+// 0x00000030: str w1, [sp, #200]
+// 0x00000034: str s0, [sp, #204]
+// 0x00000038: str w2, [sp, #208]
+// 0x0000003c: str w3, [sp, #212]
 // 0x00000040: sub sp, sp, #0x20 (32)
 // 0x00000044: .cfi_def_cfa_offset: 224
 // 0x00000044: add sp, sp, #0x20 (32)
 // 0x00000048: .cfi_def_cfa_offset: 192
 // 0x00000048: .cfi_remember_state
-// 0x00000048: ldp x19, x20, [sp, #96]
+// 0x00000048: ldp tr, x20, [sp, #96]
 // 0x0000004c: .cfi_restore: r19
 // 0x0000004c: .cfi_restore: r20
 // 0x0000004c: ldp x21, x22, [sp, #112]
@@ -235,20 +235,20 @@
     0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, 0x54, 0x55, 0x53, 0x48, 0x83,
     0xEC, 0x48, 0xF2, 0x44, 0x0F, 0x11, 0x7C, 0x24, 0x40, 0xF2, 0x44, 0x0F,
     0x11, 0x74, 0x24, 0x38, 0xF2, 0x44, 0x0F, 0x11, 0x6C, 0x24, 0x30, 0xF2,
-    0x44, 0x0F, 0x11, 0x64, 0x24, 0x28, 0x89, 0x3C, 0x24, 0x89, 0xB4, 0x24,
-    0x84, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x11, 0x84, 0x24, 0x88, 0x00, 0x00,
-    0x00, 0x89, 0x94, 0x24, 0x8C, 0x00, 0x00, 0x00, 0x89, 0x8C, 0x24, 0x90,
-    0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0xE0, 0x48, 0x83, 0xC4, 0x20, 0xF2,
-    0x44, 0x0F, 0x10, 0x64, 0x24, 0x28, 0xF2, 0x44, 0x0F, 0x10, 0x6C, 0x24,
-    0x30, 0xF2, 0x44, 0x0F, 0x10, 0x74, 0x24, 0x38, 0xF2, 0x44, 0x0F, 0x10,
-    0x7C, 0x24, 0x40, 0x48, 0x83, 0xC4, 0x48, 0x5B, 0x5D, 0x41, 0x5C, 0x41,
-    0x5D, 0x41, 0x5E, 0x41, 0x5F, 0xC3,
+    0x44, 0x0F, 0x11, 0x64, 0x24, 0x28, 0x48, 0x89, 0x3C, 0x24, 0x89, 0xB4,
+    0x24, 0x88, 0x00, 0x00, 0x00, 0xF3, 0x0F, 0x11, 0x84, 0x24, 0x8C, 0x00,
+    0x00, 0x00, 0x89, 0x94, 0x24, 0x90, 0x00, 0x00, 0x00, 0x89, 0x8C, 0x24,
+    0x94, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0xE0, 0x48, 0x83, 0xC4, 0x20,
+    0xF2, 0x44, 0x0F, 0x10, 0x64, 0x24, 0x28, 0xF2, 0x44, 0x0F, 0x10, 0x6C,
+    0x24, 0x30, 0xF2, 0x44, 0x0F, 0x10, 0x74, 0x24, 0x38, 0xF2, 0x44, 0x0F,
+    0x10, 0x7C, 0x24, 0x40, 0x48, 0x83, 0xC4, 0x48, 0x5B, 0x5D, 0x41, 0x5C,
+    0x41, 0x5D, 0x41, 0x5E, 0x41, 0x5F, 0xC3,
 };
 static constexpr uint8_t expected_cfi_kX86_64[] = {
     0x42, 0x0E, 0x10, 0x8F, 0x04, 0x42, 0x0E, 0x18, 0x8E, 0x06, 0x42, 0x0E,
     0x20, 0x8D, 0x08, 0x42, 0x0E, 0x28, 0x8C, 0x0A, 0x41, 0x0E, 0x30, 0x86,
     0x0C, 0x41, 0x0E, 0x38, 0x83, 0x0E, 0x44, 0x0E, 0x80, 0x01, 0x47, 0xA0,
-    0x10, 0x47, 0x9F, 0x12, 0x47, 0x9E, 0x14, 0x47, 0x9D, 0x16, 0x65, 0x0E,
+    0x10, 0x47, 0x9F, 0x12, 0x47, 0x9E, 0x14, 0x47, 0x9D, 0x16, 0x66, 0x0E,
     0xA0, 0x01, 0x44, 0x0E, 0x80, 0x01, 0x0A, 0x47, 0xDD, 0x47, 0xDE, 0x47,
     0xDF, 0x47, 0xE0, 0x44, 0x0E, 0x38, 0x41, 0x0E, 0x30, 0xC3, 0x41, 0x0E,
     0x28, 0xC6, 0x42, 0x0E, 0x20, 0xCC, 0x42, 0x0E, 0x18, 0xCD, 0x42, 0x0E,
@@ -282,47 +282,47 @@
 // 0x00000023: .cfi_offset: r30 at cfa-80
 // 0x00000023: movsd [rsp + 40], xmm12
 // 0x0000002a: .cfi_offset: r29 at cfa-88
-// 0x0000002a: mov [rsp], edi
-// 0x0000002d: mov [rsp + 132], esi
-// 0x00000034: movss [rsp + 136], xmm0
-// 0x0000003d: mov [rsp + 140], edx
-// 0x00000044: mov [rsp + 144], ecx
-// 0x0000004b: addq rsp, -32
-// 0x0000004f: .cfi_def_cfa_offset: 160
-// 0x0000004f: addq rsp, 32
-// 0x00000053: .cfi_def_cfa_offset: 128
-// 0x00000053: .cfi_remember_state
-// 0x00000053: movsd xmm12, [rsp + 40]
-// 0x0000005a: .cfi_restore: r29
-// 0x0000005a: movsd xmm13, [rsp + 48]
-// 0x00000061: .cfi_restore: r30
-// 0x00000061: movsd xmm14, [rsp + 56]
-// 0x00000068: .cfi_restore: r31
-// 0x00000068: movsd xmm15, [rsp + 64]
-// 0x0000006f: .cfi_restore: r32
-// 0x0000006f: addq rsp, 72
-// 0x00000073: .cfi_def_cfa_offset: 56
-// 0x00000073: pop rbx
-// 0x00000074: .cfi_def_cfa_offset: 48
-// 0x00000074: .cfi_restore: r3
-// 0x00000074: pop rbp
-// 0x00000075: .cfi_def_cfa_offset: 40
-// 0x00000075: .cfi_restore: r6
-// 0x00000075: pop r12
-// 0x00000077: .cfi_def_cfa_offset: 32
-// 0x00000077: .cfi_restore: r12
-// 0x00000077: pop r13
-// 0x00000079: .cfi_def_cfa_offset: 24
-// 0x00000079: .cfi_restore: r13
-// 0x00000079: pop r14
-// 0x0000007b: .cfi_def_cfa_offset: 16
-// 0x0000007b: .cfi_restore: r14
-// 0x0000007b: pop r15
-// 0x0000007d: .cfi_def_cfa_offset: 8
-// 0x0000007d: .cfi_restore: r15
-// 0x0000007d: ret
-// 0x0000007e: .cfi_restore_state
-// 0x0000007e: .cfi_def_cfa_offset: 128
+// 0x0000002a: movq [rsp], rdi
+// 0x0000002e: mov [rsp + 136], esi
+// 0x00000035: movss [rsp + 140], xmm0
+// 0x0000003e: mov [rsp + 144], edx
+// 0x00000045: mov [rsp + 148], ecx
+// 0x0000004c: addq rsp, -32
+// 0x00000050: .cfi_def_cfa_offset: 160
+// 0x00000050: addq rsp, 32
+// 0x00000054: .cfi_def_cfa_offset: 128
+// 0x00000054: .cfi_remember_state
+// 0x00000054: movsd xmm12, [rsp + 40]
+// 0x0000005b: .cfi_restore: r29
+// 0x0000005b: movsd xmm13, [rsp + 48]
+// 0x00000062: .cfi_restore: r30
+// 0x00000062: movsd xmm14, [rsp + 56]
+// 0x00000069: .cfi_restore: r31
+// 0x00000069: movsd xmm15, [rsp + 64]
+// 0x00000070: .cfi_restore: r32
+// 0x00000070: addq rsp, 72
+// 0x00000074: .cfi_def_cfa_offset: 56
+// 0x00000074: pop rbx
+// 0x00000075: .cfi_def_cfa_offset: 48
+// 0x00000075: .cfi_restore: r3
+// 0x00000075: pop rbp
+// 0x00000076: .cfi_def_cfa_offset: 40
+// 0x00000076: .cfi_restore: r6
+// 0x00000076: pop r12
+// 0x00000078: .cfi_def_cfa_offset: 32
+// 0x00000078: .cfi_restore: r12
+// 0x00000078: pop r13
+// 0x0000007a: .cfi_def_cfa_offset: 24
+// 0x0000007a: .cfi_restore: r13
+// 0x0000007a: pop r14
+// 0x0000007c: .cfi_def_cfa_offset: 16
+// 0x0000007c: .cfi_restore: r14
+// 0x0000007c: pop r15
+// 0x0000007e: .cfi_def_cfa_offset: 8
+// 0x0000007e: .cfi_restore: r15
+// 0x0000007e: ret
+// 0x0000007f: .cfi_restore_state
+// 0x0000007f: .cfi_def_cfa_offset: 128
 
 static constexpr uint8_t expected_asm_kMips[] = {
     0xC0, 0xFF, 0xBD, 0x27, 0x3C, 0x00, 0xBF, 0xAF, 0x38, 0x00, 0xB8, 0xAF,
@@ -397,7 +397,7 @@
 // 0x0000006c: .cfi_restore: r31
 // 0x0000006c: addiu r29, r29, 64
 // 0x00000070: .cfi_def_cfa_offset: 0
-// 0x00000070: jalr r0, r31
+// 0x00000070: jr r31
 // 0x00000074: nop
 // 0x00000078: .cfi_restore_state
 // 0x00000078: .cfi_def_cfa_offset: 64
@@ -406,8 +406,8 @@
     0xA0, 0xFF, 0xBD, 0x67, 0x58, 0x00, 0xBF, 0xFF, 0x50, 0x00, 0xBE, 0xFF,
     0x48, 0x00, 0xBC, 0xFF, 0x40, 0x00, 0xB7, 0xFF, 0x38, 0x00, 0xB6, 0xFF,
     0x30, 0x00, 0xB5, 0xFF, 0x28, 0x00, 0xB4, 0xFF, 0x20, 0x00, 0xB3, 0xFF,
-    0x18, 0x00, 0xB2, 0xFF, 0x00, 0x00, 0xA4, 0xAF, 0x64, 0x00, 0xA5, 0xAF,
-    0x68, 0x00, 0xAE, 0xE7, 0x6C, 0x00, 0xA7, 0xAF, 0x70, 0x00, 0xA8, 0xAF,
+    0x18, 0x00, 0xB2, 0xFF, 0x00, 0x00, 0xA4, 0xFF, 0x68, 0x00, 0xA5, 0xAF,
+    0x6C, 0x00, 0xAE, 0xE7, 0x70, 0x00, 0xA7, 0xAF, 0x74, 0x00, 0xA8, 0xAF,
     0xE0, 0xFF, 0xBD, 0x67, 0x20, 0x00, 0xBD, 0x67, 0x18, 0x00, 0xB2, 0xDF,
     0x20, 0x00, 0xB3, 0xDF, 0x28, 0x00, 0xB4, 0xDF, 0x30, 0x00, 0xB5, 0xDF,
     0x38, 0x00, 0xB6, 0xDF, 0x40, 0x00, 0xB7, 0xDF, 0x48, 0x00, 0xBC, 0xDF,
@@ -442,11 +442,11 @@
 // 0x00000024: .cfi_offset: r19 at cfa-64
 // 0x00000024: sd r18, +24(r29)
 // 0x00000028: .cfi_offset: r18 at cfa-72
-// 0x00000028: sw r4, +0(r29)
-// 0x0000002c: sw r5, +100(r29)
-// 0x00000030: swc1 f14, +104(r29)
-// 0x00000034: sw r7, +108(r29)
-// 0x00000038: sw r8, +112(r29)
+// 0x00000028: sd r4, +0(r29)
+// 0x0000002c: sw r5, +104(r29)
+// 0x00000030: swc1 f14, +108(r29)
+// 0x00000034: sw r7, +112(r29)
+// 0x00000038: sw r8, +116(r29)
 // 0x0000003c: daddiu r29, r29, -32
 // 0x00000040: .cfi_def_cfa_offset: 128
 // 0x00000040: daddiu r29, r29, 32
@@ -476,4 +476,3 @@
 // 0x00000070: nop
 // 0x00000074: .cfi_restore_state
 // 0x00000074: .cfi_def_cfa_offset: 96
-
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index 4186891..e98e572 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -18,6 +18,7 @@
 
 #include <math.h>
 
+#include "art_method-inl.h"
 #include "class_linker.h"
 #include "common_compiler_test.h"
 #include "dex_file.h"
@@ -25,7 +26,6 @@
 #include "indirect_reference_table.h"
 #include "jni_internal.h"
 #include "mem_map.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/object_array-inl.h"
@@ -65,12 +65,9 @@
         hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
     // Compile the native method before starting the runtime
     mirror::Class* c = class_linker_->FindClass(soa.Self(), "LMyClassNatives;", loader);
-    mirror::ArtMethod* method;
-    if (direct) {
-      method = c->FindDirectMethod(method_name, method_sig);
-    } else {
-      method = c->FindVirtualMethod(method_name, method_sig);
-    }
+    const auto pointer_size = class_linker_->GetImagePointerSize();
+    ArtMethod* method = direct ? c->FindDirectMethod(method_name, method_sig, pointer_size) :
+        c->FindVirtualMethod(method_name, method_sig, pointer_size);
     ASSERT_TRUE(method != nullptr) << method_name << " " << method_sig;
     if (check_generic_jni_) {
       method->SetEntryPointFromQuickCompiledCode(class_linker_->GetRuntimeQuickGenericJniStub());
diff --git a/compiler/jni/quick/arm/calling_convention_arm.cc b/compiler/jni/quick/arm/calling_convention_arm.cc
index d3690b2..9d2732a 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.cc
+++ b/compiler/jni/quick/arm/calling_convention_arm.cc
@@ -257,8 +257,7 @@
 
 size_t ArmJniCallingConvention::FrameSize() {
   // Method*, LR and callee save area size, local reference segment state
-  size_t frame_data_size = sizeof(StackReference<mirror::ArtMethod>) +
-      (2 + CalleeSaveRegisters().size()) * kFramePointerSize;
+  size_t frame_data_size = kArmPointerSize + (2 + CalleeSaveRegisters().size()) * kFramePointerSize;
   // References plus 2 words for HandleScope header
   size_t handle_scope_size = HandleScope::SizeOf(kFramePointerSize, ReferenceCount());
   // Plus return value spill area size
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.cc b/compiler/jni/quick/arm64/calling_convention_arm64.cc
index 8e7fd2b..9aef10e 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.cc
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.cc
@@ -99,8 +99,8 @@
 FrameOffset Arm64ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
   CHECK(IsCurrentParamOnStack());
   FrameOffset result =
-      FrameOffset(displacement_.Int32Value() +   // displacement
-                  sizeof(StackReference<mirror::ArtMethod>) +  // Method ref
+      FrameOffset(displacement_.Int32Value() +  // displacement
+                  kFramePointerSize +  // Method ref
                   (itr_slots_ * sizeof(uint32_t)));  // offset into in args
   return result;
 }
@@ -206,7 +206,7 @@
 
 size_t Arm64JniCallingConvention::FrameSize() {
   // Method*, callee save area size, local reference segment state
-  size_t frame_data_size = sizeof(StackReference<mirror::ArtMethod>) +
+  size_t frame_data_size = kFramePointerSize +
       CalleeSaveRegisters().size() * kFramePointerSize + sizeof(uint32_t);
   // References plus 2 words for HandleScope header
   size_t handle_scope_size = HandleScope::SizeOf(kFramePointerSize, ReferenceCount());
diff --git a/compiler/jni/quick/calling_convention.cc b/compiler/jni/quick/calling_convention.cc
index 2e146c4..bb8136b 100644
--- a/compiler/jni/quick/calling_convention.cc
+++ b/compiler/jni/quick/calling_convention.cc
@@ -131,7 +131,7 @@
 
 FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
   size_t references_size = handle_scope_pointer_size_ * ReferenceCount();  // size excluding header
-  return FrameOffset(HandleerencesOffset().Int32Value() + references_size);
+  return FrameOffset(HandleReferencesOffset().Int32Value() + references_size);
 }
 
 FrameOffset JniCallingConvention::ReturnValueSaveLocation() const {
@@ -228,7 +228,7 @@
 FrameOffset JniCallingConvention::CurrentParamHandleScopeEntryOffset() {
   CHECK(IsCurrentParamAReference());
   CHECK_LT(HandleScopeLinkOffset(), HandleScopeNumRefsOffset());
-  int result = HandleerencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_;
+  int result = HandleReferencesOffset().Int32Value() + itr_refs_ * handle_scope_pointer_size_;
   CHECK_GT(result, HandleScopeNumRefsOffset().Int32Value());
   return FrameOffset(result);
 }
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h
index 0c64a36..c9b595a 100644
--- a/compiler/jni/quick/calling_convention.h
+++ b/compiler/jni/quick/calling_convention.h
@@ -171,7 +171,7 @@
     if (IsStatic()) {
       param++;  // 0th argument must skip return value at start of the shorty
     } else if (param == 0) {
-      return frame_pointer_size_;  // this argument
+      return sizeof(mirror::HeapReference<mirror::Object>);  // this argument
     }
     size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[param]));
     if (result >= 1 && result < 4) {
@@ -196,7 +196,7 @@
   unsigned int itr_float_and_doubles_;
   // Space for frames below this on the stack.
   FrameOffset displacement_;
-  // The size of a reference.
+  // The size of a pointer.
   const size_t frame_pointer_size_;
   // The size of a reference entry within the handle scope.
   const size_t handle_scope_pointer_size_;
@@ -320,12 +320,13 @@
 
   // Position of handle scope and interior fields
   FrameOffset HandleScopeOffset() const {
-    return FrameOffset(this->displacement_.Int32Value() + sizeof(StackReference<mirror::ArtMethod>));
+    return FrameOffset(this->displacement_.Int32Value() + frame_pointer_size_);
     // above Method reference
   }
 
   FrameOffset HandleScopeLinkOffset() const {
-    return FrameOffset(HandleScopeOffset().Int32Value() + HandleScope::LinkOffset(frame_pointer_size_));
+    return FrameOffset(HandleScopeOffset().Int32Value() +
+                       HandleScope::LinkOffset(frame_pointer_size_));
   }
 
   FrameOffset HandleScopeNumRefsOffset() const {
@@ -333,7 +334,7 @@
                        HandleScope::NumberOfReferencesOffset(frame_pointer_size_));
   }
 
-  FrameOffset HandleerencesOffset() const {
+  FrameOffset HandleReferencesOffset() const {
     return FrameOffset(HandleScopeOffset().Int32Value() +
                        HandleScope::ReferencesOffset(frame_pointer_size_));
   }
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 573c088..4d7d86c 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -21,6 +21,7 @@
 #include <vector>
 #include <fstream>
 
+#include "art_method.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "calling_convention.h"
@@ -31,7 +32,6 @@
 #include "driver/compiler_options.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "jni_env_ext.h"
-#include "mirror/art_method.h"
 #include "utils/assembler.h"
 #include "utils/managed_register.h"
 #include "utils/arm/managed_register_arm.h"
@@ -117,18 +117,18 @@
 
   if (is_64_bit_target) {
     __ CopyRawPtrFromThread64(main_jni_conv->HandleScopeLinkOffset(),
-                            Thread::TopHandleScopeOffset<8>(),
-                            mr_conv->InterproceduralScratchRegister());
+                              Thread::TopHandleScopeOffset<8>(),
+                              mr_conv->InterproceduralScratchRegister());
     __ StoreStackOffsetToThread64(Thread::TopHandleScopeOffset<8>(),
-                                main_jni_conv->HandleScopeOffset(),
-                                mr_conv->InterproceduralScratchRegister());
+                                  main_jni_conv->HandleScopeOffset(),
+                                  mr_conv->InterproceduralScratchRegister());
   } else {
     __ CopyRawPtrFromThread32(main_jni_conv->HandleScopeLinkOffset(),
-                            Thread::TopHandleScopeOffset<4>(),
-                            mr_conv->InterproceduralScratchRegister());
+                              Thread::TopHandleScopeOffset<4>(),
+                              mr_conv->InterproceduralScratchRegister());
     __ StoreStackOffsetToThread32(Thread::TopHandleScopeOffset<4>(),
-                                main_jni_conv->HandleScopeOffset(),
-                                mr_conv->InterproceduralScratchRegister());
+                                  main_jni_conv->HandleScopeOffset(),
+                                  mr_conv->InterproceduralScratchRegister());
   }
 
   // 3. Place incoming reference arguments into handle scope
@@ -138,10 +138,10 @@
     FrameOffset handle_scope_offset = main_jni_conv->CurrentParamHandleScopeEntryOffset();
     // Check handle scope offset is within frame
     CHECK_LT(handle_scope_offset.Uint32Value(), frame_size);
-    // Note this LoadRef() already includes the heap poisoning negation.
+    // Note this LoadRef() doesn't need heap poisoning since its from the ArtMethod.
     // Note this LoadRef() does not include read barrier. It will be handled below.
     __ LoadRef(main_jni_conv->InterproceduralScratchRegister(),
-               mr_conv->MethodRegister(), mirror::ArtMethod::DeclaringClassOffset());
+               mr_conv->MethodRegister(), ArtMethod::DeclaringClassOffset(), false);
     __ VerifyObject(main_jni_conv->InterproceduralScratchRegister(), false);
     __ StoreRef(handle_scope_offset, main_jni_conv->InterproceduralScratchRegister());
     main_jni_conv->Next();  // in handle scope so move to next argument
@@ -251,12 +251,11 @@
     if (main_jni_conv->IsCurrentParamOnStack()) {
       FrameOffset out_off = main_jni_conv->CurrentParamStackOffset();
       __ CreateHandleScopeEntry(out_off, locked_object_handle_scope_offset,
-                         mr_conv->InterproceduralScratchRegister(),
-                         false);
+                                mr_conv->InterproceduralScratchRegister(), false);
     } else {
       ManagedRegister out_reg = main_jni_conv->CurrentParamRegister();
       __ CreateHandleScopeEntry(out_reg, locked_object_handle_scope_offset,
-                         ManagedRegister::NoRegister(), false);
+                                ManagedRegister::NoRegister(), false);
     }
     main_jni_conv->Next();
   }
@@ -264,10 +263,10 @@
     __ GetCurrentThread(main_jni_conv->CurrentParamRegister());
     if (is_64_bit_target) {
       __ Call(main_jni_conv->CurrentParamRegister(), Offset(jni_start64),
-             main_jni_conv->InterproceduralScratchRegister());
+              main_jni_conv->InterproceduralScratchRegister());
     } else {
       __ Call(main_jni_conv->CurrentParamRegister(), Offset(jni_start32),
-             main_jni_conv->InterproceduralScratchRegister());
+              main_jni_conv->InterproceduralScratchRegister());
     }
   } else {
     __ GetCurrentThread(main_jni_conv->CurrentParamStackOffset(),
@@ -347,15 +346,15 @@
     FrameOffset jni_env = main_jni_conv->CurrentParamStackOffset();
     if (is_64_bit_target) {
       __ CopyRawPtrFromThread64(jni_env, Thread::JniEnvOffset<8>(),
-                            main_jni_conv->InterproceduralScratchRegister());
+                                main_jni_conv->InterproceduralScratchRegister());
     } else {
       __ CopyRawPtrFromThread32(jni_env, Thread::JniEnvOffset<4>(),
-                            main_jni_conv->InterproceduralScratchRegister());
+                                main_jni_conv->InterproceduralScratchRegister());
     }
   }
 
   // 9. Plant call to native code associated with method.
-  MemberOffset jni_entrypoint_offset = mirror::ArtMethod::EntryPointFromJniOffset(
+  MemberOffset jni_entrypoint_offset = ArtMethod::EntryPointFromJniOffset(
       InstructionSetPointerSize(instruction_set));
   __ Call(main_jni_conv->MethodStackOffset(), jni_entrypoint_offset,
           mr_conv->InterproceduralScratchRegister());
diff --git a/compiler/jni/quick/mips/calling_convention_mips.cc b/compiler/jni/quick/mips/calling_convention_mips.cc
index aefbf06..4e716b5 100644
--- a/compiler/jni/quick/mips/calling_convention_mips.cc
+++ b/compiler/jni/quick/mips/calling_convention_mips.cc
@@ -148,7 +148,7 @@
 
 size_t MipsJniCallingConvention::FrameSize() {
   // Method*, LR and callee save area size, local reference segment state
-  size_t frame_data_size = sizeof(StackReference<mirror::ArtMethod>) +
+  size_t frame_data_size = kMipsPointerSize +
       (2 + CalleeSaveRegisters().size()) * kFramePointerSize;
   // References plus 2 words for HandleScope header
   size_t handle_scope_size = HandleScope::SizeOf(kFramePointerSize, ReferenceCount());
diff --git a/compiler/jni/quick/mips64/calling_convention_mips64.cc b/compiler/jni/quick/mips64/calling_convention_mips64.cc
index d446867..3a11bcf 100644
--- a/compiler/jni/quick/mips64/calling_convention_mips64.cc
+++ b/compiler/jni/quick/mips64/calling_convention_mips64.cc
@@ -84,9 +84,9 @@
 FrameOffset Mips64ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
   CHECK(IsCurrentParamOnStack());
   FrameOffset result =
-      FrameOffset(displacement_.Int32Value() +                 // displacement
-                  sizeof(StackReference<mirror::ArtMethod>) +  // Method ref
-                  (itr_slots_ * sizeof(uint32_t)));            // offset into in args
+      FrameOffset(displacement_.Int32Value() +  // displacement
+                  kFramePointerSize +  // Method ref
+                  (itr_slots_ * sizeof(uint32_t)));  // offset into in args
   return result;
 }
 
@@ -149,7 +149,7 @@
 
 size_t Mips64JniCallingConvention::FrameSize() {
   // Mehtod* and callee save area size, local reference segment state
-  size_t frame_data_size = sizeof(StackReference<mirror::ArtMethod>) +
+  size_t frame_data_size = kFramePointerSize +
       CalleeSaveRegisters().size() * kFramePointerSize + sizeof(uint32_t);
   // References plus 2 words for HandleScope header
   size_t handle_scope_size = HandleScope::SizeOf(kFramePointerSize, ReferenceCount());
diff --git a/compiler/jni/quick/x86/calling_convention_x86.cc b/compiler/jni/quick/x86/calling_convention_x86.cc
index 499dd7c..322caca 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.cc
+++ b/compiler/jni/quick/x86/calling_convention_x86.cc
@@ -180,7 +180,7 @@
 
 size_t X86JniCallingConvention::FrameSize() {
   // Method*, return address and callee save area size, local reference segment state
-  size_t frame_data_size = sizeof(StackReference<mirror::ArtMethod>) +
+  size_t frame_data_size = kX86PointerSize +
       (2 + CalleeSaveRegisters().size()) * kFramePointerSize;
   // References plus 2 words for HandleScope header
   size_t handle_scope_size = HandleScope::SizeOf(kFramePointerSize, ReferenceCount());
diff --git a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
index 7e92d12..9c7eab1 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
@@ -97,9 +97,9 @@
 }
 
 FrameOffset X86_64ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
-  return FrameOffset(displacement_.Int32Value() +   // displacement
-                     sizeof(StackReference<mirror::ArtMethod>) +  // Method ref
-                     (itr_slots_ * sizeof(uint32_t)));  // offset into in args
+  return FrameOffset(displacement_.Int32Value() +  // displacement
+                     kX86_64PointerSize +  // Method ref
+                     itr_slots_ * sizeof(uint32_t));  // offset into in args
 }
 
 const ManagedRegisterEntrySpills& X86_64ManagedRuntimeCallingConvention::EntrySpills() {
@@ -149,7 +149,7 @@
 
 size_t X86_64JniCallingConvention::FrameSize() {
   // Method*, return address and callee save area size, local reference segment state
-  size_t frame_data_size = sizeof(StackReference<mirror::ArtMethod>) +
+  size_t frame_data_size = kX86_64PointerSize +
       (2 + CalleeSaveRegisters().size()) * kFramePointerSize;
   // References plus link_ (pointer) and number_of_references_ (uint32_t) for HandleScope header
   size_t handle_scope_size = HandleScope::SizeOf(kFramePointerSize, ReferenceCount());
diff --git a/compiler/linker/arm/relative_patcher_thumb2.cc b/compiler/linker/arm/relative_patcher_thumb2.cc
index b17cbca..d010430 100644
--- a/compiler/linker/arm/relative_patcher_thumb2.cc
+++ b/compiler/linker/arm/relative_patcher_thumb2.cc
@@ -16,8 +16,8 @@
 
 #include "linker/arm/relative_patcher_thumb2.h"
 
+#include "art_method.h"
 #include "compiled_method.h"
-#include "mirror/art_method.h"
 #include "utils/arm/assembler_thumb2.h"
 
 namespace art {
@@ -80,7 +80,7 @@
   arm::Thumb2Assembler assembler;
   assembler.LoadFromOffset(
       arm::kLoadWord, arm::PC, arm::R0,
-      mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArmPointerSize).Int32Value());
+      ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArmPointerSize).Int32Value());
   assembler.bkpt(0);
   std::vector<uint8_t> thunk_code(assembler.CodeSize());
   MemoryRegion code(thunk_code.data(), thunk_code.size());
diff --git a/compiler/linker/arm64/relative_patcher_arm64.cc b/compiler/linker/arm64/relative_patcher_arm64.cc
index 72ddf07..ee48789 100644
--- a/compiler/linker/arm64/relative_patcher_arm64.cc
+++ b/compiler/linker/arm64/relative_patcher_arm64.cc
@@ -17,9 +17,9 @@
 #include "linker/arm64/relative_patcher_arm64.h"
 
 #include "arch/arm64/instruction_set_features_arm64.h"
+#include "art_method.h"
 #include "compiled_method.h"
 #include "driver/compiler_driver.h"
-#include "mirror/art_method.h"
 #include "utils/arm64/assembler_arm64.h"
 #include "oat.h"
 #include "output_stream.h"
@@ -158,6 +158,8 @@
   uint32_t insn = GetInsn(code, literal_offset);
   uint32_t pc_insn_offset = patch.PcInsnOffset();
   uint32_t disp = target_offset - ((patch_offset - literal_offset + pc_insn_offset) & ~0xfffu);
+  bool wide = (insn & 0x40000000) != 0;
+  uint32_t shift = wide ? 3u : 2u;
   if (literal_offset == pc_insn_offset) {
     // Check it's an ADRP with imm == 0 (unset).
     DCHECK_EQ((insn & 0xffffffe0u), 0x90000000u)
@@ -173,7 +175,7 @@
       uint32_t out_disp = thunk_offset - patch_offset;
       DCHECK_EQ(out_disp & 3u, 0u);
       DCHECK((out_disp >> 27) == 0u || (out_disp >> 27) == 31u);  // 28-bit signed.
-      insn = (out_disp & 0x0fffffffu) >> 2;
+      insn = (out_disp & 0x0fffffffu) >> shift;
       insn |= 0x14000000;  // B <thunk>
 
       uint32_t back_disp = -out_disp;
@@ -194,7 +196,8 @@
     // Write the new ADRP (or B to the erratum 843419 thunk).
     SetInsn(code, literal_offset, insn);
   } else {
-    DCHECK_EQ(insn & 0xfffffc00, 0xb9400000);  // LDR 32-bit with imm12 == 0 (unset).
+    // LDR 32-bit or 64-bit with imm12 == 0 (unset).
+    DCHECK_EQ(insn & 0xbffffc00, 0xb9400000) << insn;
     if (kIsDebugBuild) {
       uint32_t adrp = GetInsn(code, pc_insn_offset);
       if ((adrp & 0x9f000000u) != 0x90000000u) {
@@ -216,7 +219,7 @@
       CHECK_EQ(adrp & 0x9f00001fu,                    // Check that pc_insn_offset points
                0x90000000 | ((insn >> 5) & 0x1fu));   // to ADRP with matching register.
     }
-    uint32_t imm12 = (disp & 0xfffu) >> 2;
+    uint32_t imm12 = (disp & 0xfffu) >> shift;
     insn = (insn & ~(0xfffu << 10)) | (imm12 << 10);
     SetInsn(code, literal_offset, insn);
   }
@@ -226,7 +229,7 @@
   // The thunk just uses the entry point in the ArtMethod. This works even for calls
   // to the generic JNI and interpreter trampolines.
   arm64::Arm64Assembler assembler;
-  Offset offset(mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+  Offset offset(ArtMethod::EntryPointFromQuickCompiledCodeOffset(
       kArm64PointerSize).Int32Value());
   assembler.JumpTo(ManagedRegister(arm64::X0), offset, ManagedRegister(arm64::IP0));
   // Ensure we emit the literal pool.
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index a871a82..0747756 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -15,6 +15,7 @@
  */
 
 #include "arch/instruction_set_features.h"
+#include "art_method-inl.h"
 #include "class_linker.h"
 #include "common_compiler_test.h"
 #include "compiled_method.h"
@@ -26,7 +27,6 @@
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
 #include "entrypoints/quick/quick_entrypoints.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
@@ -41,7 +41,7 @@
  protected:
   static const bool kCompile = false;  // DISABLED_ due to the time to compile libcore
 
-  void CheckMethod(mirror::ArtMethod* method,
+  void CheckMethod(ArtMethod* method,
                    const OatFile::OatMethod& oat_method,
                    const DexFile& dex_file)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -140,16 +140,18 @@
   ASSERT_TRUE(oat_dex_file != nullptr);
   CHECK_EQ(dex_file.GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
   ScopedObjectAccess soa(Thread::Current());
+  auto pointer_size = class_linker->GetImagePointerSize();
   for (size_t i = 0; i < dex_file.NumClassDefs(); i++) {
     const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
     const uint8_t* class_data = dex_file.GetClassData(class_def);
+
     size_t num_virtual_methods = 0;
     if (class_data != nullptr) {
       ClassDataItemIterator it(dex_file, class_data);
       num_virtual_methods = it.NumVirtualMethods();
     }
+
     const char* descriptor = dex_file.GetClassDescriptor(class_def);
-    StackHandleScope<1> hs(soa.Self());
     mirror::Class* klass = class_linker->FindClass(soa.Self(), descriptor,
                                                    NullHandle<mirror::ClassLoader>());
 
@@ -159,14 +161,19 @@
              oat_class.GetType()) << descriptor;
 
     size_t method_index = 0;
-    for (size_t j = 0; j < klass->NumDirectMethods(); j++, method_index++) {
-      CheckMethod(klass->GetDirectMethod(j),
-                  oat_class.GetOatMethod(method_index), dex_file);
+    for (auto& m : klass->GetDirectMethods(pointer_size)) {
+      CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
+      ++method_index;
     }
-    for (size_t j = 0; j < num_virtual_methods; j++, method_index++) {
-      CheckMethod(klass->GetVirtualMethod(j),
-                  oat_class.GetOatMethod(method_index), dex_file);
+    size_t visited_virtuals = 0;
+    for (auto& m : klass->GetVirtualMethods(pointer_size)) {
+      if (!m.IsMiranda()) {
+        CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
+        ++method_index;
+        ++visited_virtuals;
+      }
     }
+    EXPECT_EQ(visited_virtuals, num_virtual_methods);
   }
 }
 
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 8f153b1..a98a304 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -19,6 +19,7 @@
 #include <zlib.h>
 
 #include "arch/arm64/instruction_set_features_arm64.h"
+#include "art_method-inl.h"
 #include "base/allocator.h"
 #include "base/bit_vector.h"
 #include "base/stl_util.h"
@@ -33,7 +34,6 @@
 #include "gc/space/space.h"
 #include "image_writer.h"
 #include "linker/relative_patcher.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/array.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache-inl.h"
@@ -615,10 +615,9 @@
     ScopedObjectAccessUnchecked soa(Thread::Current());
     StackHandleScope<1> hs(soa.Self());
     Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(*dex_file_)));
-    mirror::ArtMethod* method = linker->ResolveMethod(*dex_file_, it.GetMemberIndex(), dex_cache,
-                                                      NullHandle<mirror::ClassLoader>(),
-                                                      NullHandle<mirror::ArtMethod>(),
-                                                      invoke_type);
+    ArtMethod* method = linker->ResolveMethod(
+        *dex_file_, it.GetMemberIndex(), dex_cache, NullHandle<mirror::ClassLoader>(), nullptr,
+        invoke_type);
     if (method == nullptr) {
       LOG(ERROR) << "Unexpected failure to resolve a method: "
                  << PrettyMethod(it.GetMemberIndex(), *dex_file_, true);
@@ -750,8 +749,8 @@
                 uint32_t target_offset = GetTargetOffset(patch);
                 PatchCodeAddress(&patched_code_, patch.LiteralOffset(), target_offset);
               } else if (patch.Type() == kLinkerPatchMethod) {
-                mirror::ArtMethod* method = GetTargetMethod(patch);
-                PatchObjectAddress(&patched_code_, patch.LiteralOffset(), method);
+                ArtMethod* method = GetTargetMethod(patch);
+                PatchMethodAddress(&patched_code_, patch.LiteralOffset(), method);
               } else if (patch.Type() == kLinkerPatchType) {
                 mirror::Class* type = GetTargetType(patch);
                 PatchObjectAddress(&patched_code_, patch.LiteralOffset(), type);
@@ -789,12 +788,13 @@
         << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " to " << out_->GetLocation();
   }
 
-  mirror::ArtMethod* GetTargetMethod(const LinkerPatch& patch)
+  ArtMethod* GetTargetMethod(const LinkerPatch& patch)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     MethodReference ref = patch.TargetMethod();
     mirror::DexCache* dex_cache =
         (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache(*ref.dex_file);
-    mirror::ArtMethod* method = dex_cache->GetResolvedMethod(ref.dex_method_index);
+    ArtMethod* method = dex_cache->GetResolvedMethod(
+        ref.dex_method_index, class_linker_->GetImagePointerSize());
     CHECK(method != nullptr);
     return method;
   }
@@ -805,7 +805,7 @@
         (target_it != writer_->method_offset_map_.map.end()) ? target_it->second : 0u;
     // If there's no compiled code, point to the correct trampoline.
     if (UNLIKELY(target_offset == 0)) {
-      mirror::ArtMethod* target = GetTargetMethod(patch);
+      ArtMethod* target = GetTargetMethod(patch);
       DCHECK(target != nullptr);
       size_t size = GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet());
       const void* oat_code_offset = target->GetEntryPointFromQuickCompiledCodePtrSize(size);
@@ -860,6 +860,23 @@
     data[3] = (address >> 24) & 0xffu;
   }
 
+  void PatchMethodAddress(std::vector<uint8_t>* code, uint32_t offset, ArtMethod* method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    // NOTE: Direct method pointers across oat files don't use linker patches. However, direct
+    // type pointers across oat files do. (TODO: Investigate why.)
+    if (writer_->image_writer_ != nullptr) {
+      method = writer_->image_writer_->GetImageMethodAddress(method);
+    }
+    // Note: We only patch ArtMethods to low 4gb since thats where the image is.
+    uint32_t address = PointerToLowMemUInt32(method);
+    DCHECK_LE(offset + 4, code->size());
+    uint8_t* data = &(*code)[offset];
+    data[0] = address & 0xffu;
+    data[1] = (address >> 8) & 0xffu;
+    data[2] = (address >> 16) & 0xffu;
+    data[3] = (address >> 24) & 0xffu;
+  }
+
   void PatchCodeAddress(std::vector<uint8_t>* code, uint32_t offset, uint32_t target_offset)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     uint32_t address = writer_->image_writer_ == nullptr ? target_offset :
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 411a5aa..f98029d 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -663,9 +663,8 @@
               *dex_compilation_unit_->GetDexFile())));
       Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
           soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
-      mirror::ArtMethod* resolved_method = compiler_driver_->ResolveMethod(
-          soa, dex_cache, class_loader, dex_compilation_unit_, method_idx,
-          optimized_invoke_type);
+      ArtMethod* resolved_method = compiler_driver_->ResolveMethod(
+          soa, dex_cache, class_loader, dex_compilation_unit_, method_idx, optimized_invoke_type);
 
       if (resolved_method == nullptr) {
         MaybeRecordStat(MethodCompilationStat::kNotCompiledUnresolvedMethod);
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index d71266d..c106d30 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -114,6 +114,11 @@
   return mirror::ObjectArray<mirror::Object>::OffsetOfElement(index).SizeValue();
 }
 
+size_t CodeGenerator::GetCachePointerOffset(uint32_t index) {
+  auto pointer_size = InstructionSetPointerSize(GetInstructionSet());
+  return mirror::Array::DataOffset(pointer_size).Uint32Value() + pointer_size * index;
+}
+
 void CodeGenerator::CompileBaseline(CodeAllocator* allocator, bool is_leaf) {
   Initialize();
   if (!is_leaf) {
@@ -270,7 +275,8 @@
   uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs();
   if (reg_number >= number_of_locals) {
     // Local is a parameter of the method. It is stored in the caller's frame.
-    return GetFrameSize() + kVRegSize  // ART method
+    // TODO: Share this logic with StackVisitor::GetVRegOffsetFromQuickCode.
+    return GetFrameSize() + InstructionSetPointerSize(GetInstructionSet())  // ART method
                           + (reg_number - number_of_locals) * kVRegSize;
   } else {
     // Local is a temporary in this method. It is stored in this method's frame.
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 740beab..3012098 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -152,7 +152,7 @@
   size_t GetStackSlotOfParameter(HParameterValue* parameter) const {
     // Note that this follows the current calling convention.
     return GetFrameSize()
-        + kVRegSize  // Art method
+        + InstructionSetPointerSize(GetInstructionSet())  // Art method
         + parameter->GetIndex() * kVRegSize;
   }
 
@@ -273,6 +273,8 @@
   // Note: this method assumes we always have the same pointer size, regardless
   // of the architecture.
   static size_t GetCacheOffset(uint32_t index);
+  // Pointer variant for ArtMethod and ArtField arrays.
+  size_t GetCachePointerOffset(uint32_t index);
 
   void EmitParallelMoves(Location from1,
                          Location to1,
@@ -477,11 +479,13 @@
   CallingConvention(const C* registers,
                     size_t number_of_registers,
                     const F* fpu_registers,
-                    size_t number_of_fpu_registers)
+                    size_t number_of_fpu_registers,
+                    size_t pointer_size)
       : registers_(registers),
         number_of_registers_(number_of_registers),
         fpu_registers_(fpu_registers),
-        number_of_fpu_registers_(number_of_fpu_registers) {}
+        number_of_fpu_registers_(number_of_fpu_registers),
+        pointer_size_(pointer_size) {}
 
   size_t GetNumberOfRegisters() const { return number_of_registers_; }
   size_t GetNumberOfFpuRegisters() const { return number_of_fpu_registers_; }
@@ -498,8 +502,8 @@
 
   size_t GetStackOffsetOf(size_t index) const {
     // We still reserve the space for parameters passed by registers.
-    // Add one for the method pointer.
-    return (index + 1) * kVRegSize;
+    // Add space for the method pointer.
+    return pointer_size_ + index * kVRegSize;
   }
 
  private:
@@ -507,6 +511,7 @@
   const size_t number_of_registers_;
   const F* fpu_registers_;
   const size_t number_of_fpu_registers_;
+  const size_t pointer_size_;
 
   DISALLOW_COPY_AND_ASSIGN(CallingConvention);
 };
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index bd1f134..7f0be05 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -17,14 +17,14 @@
 #include "code_generator_arm.h"
 
 #include "arch/arm/instruction_set_features_arm.h"
+#include "art_method.h"
 #include "code_generator_utils.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "gc/accounting/card_table.h"
 #include "intrinsics.h"
 #include "intrinsics_arm.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method.h"
-#include "mirror/class.h"
+#include "mirror/class-inl.h"
 #include "thread.h"
 #include "utils/arm/assembler_arm.h"
 #include "utils/arm/managed_register_arm.h"
@@ -1314,8 +1314,8 @@
   }
 
   Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
-  uint32_t method_offset = mirror::Class::EmbeddedVTableOffset().Uint32Value() +
-          invoke->GetVTableIndex() * sizeof(mirror::Class::VTableEntry);
+  uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
+      invoke->GetVTableIndex(), kArmPointerSize).Uint32Value();
   LocationSummary* locations = invoke->GetLocations();
   Location receiver = locations->InAt(0);
   uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
@@ -1328,7 +1328,7 @@
   }
   codegen_->MaybeRecordImplicitNullCheck(invoke);
   // temp = temp->GetMethodAt(method_offset);
-  uint32_t entry_point = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+  uint32_t entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(
       kArmWordSize).Int32Value();
   __ LoadFromOffset(kLoadWord, temp, temp, method_offset);
   // LR = temp->GetEntryPoint();
@@ -1348,8 +1348,8 @@
 void InstructionCodeGeneratorARM::VisitInvokeInterface(HInvokeInterface* invoke) {
   // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError.
   Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
-  uint32_t method_offset = mirror::Class::EmbeddedImTableOffset().Uint32Value() +
-          (invoke->GetImtIndex() % mirror::Class::kImtSize) * sizeof(mirror::Class::ImTableEntry);
+  uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset(
+      invoke->GetImtIndex() % mirror::Class::kImtSize, kArmPointerSize).Uint32Value();
   LocationSummary* locations = invoke->GetLocations();
   Location receiver = locations->InAt(0);
   uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
@@ -1367,7 +1367,7 @@
   }
   codegen_->MaybeRecordImplicitNullCheck(invoke);
   // temp = temp->GetImtEntryAt(method_offset);
-  uint32_t entry_point = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+  uint32_t entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(
       kArmWordSize).Int32Value();
   __ LoadFromOffset(kLoadWord, temp, temp, method_offset);
   // LR = temp->GetEntryPoint();
@@ -3977,13 +3977,13 @@
     DCHECK(!cls->CanCallRuntime());
     DCHECK(!cls->MustGenerateClinitCheck());
     __ LoadFromOffset(
-        kLoadWord, out, current_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value());
+        kLoadWord, out, current_method, ArtMethod::DeclaringClassOffset().Int32Value());
   } else {
     DCHECK(cls->CanCallRuntime());
     __ LoadFromOffset(kLoadWord,
                       out,
                       current_method,
-                      mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value());
+                      ArtMethod::DexCacheResolvedTypesOffset().Int32Value());
     __ LoadFromOffset(kLoadWord, out, out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex()));
 
     SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
@@ -4043,7 +4043,7 @@
   Register out = locations->Out().AsRegister<Register>();
   Register current_method = locations->InAt(0).AsRegister<Register>();
   __ LoadFromOffset(
-      kLoadWord, out, current_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value());
+      kLoadWord, out, current_method, ArtMethod::DeclaringClassOffset().Int32Value());
   __ LoadFromOffset(kLoadWord, out, out, mirror::Class::DexCacheStringsOffset().Int32Value());
   __ LoadFromOffset(kLoadWord, out, out, CodeGenerator::GetCacheOffset(load->GetStringIndex()));
   __ cmp(out, ShifterOperand(0));
@@ -4268,7 +4268,7 @@
     __ LoadFromOffset(kLoadWord, temp, TR, invoke->GetStringInitOffset());
     // LR = temp[offset_of_quick_compiled_code]
     __ LoadFromOffset(kLoadWord, LR, temp,
-                      mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+                      ArtMethod::EntryPointFromQuickCompiledCodeOffset(
                           kArmWordSize).Int32Value());
     // LR()
     __ blx(LR);
@@ -4278,14 +4278,13 @@
     if (!invoke->IsRecursive()) {
       // temp = temp->dex_cache_resolved_methods_;
       __ LoadFromOffset(
-          kLoadWord, temp, temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value());
+          kLoadWord, temp, temp, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value());
       // temp = temp[index_in_cache]
       __ LoadFromOffset(
           kLoadWord, temp, temp, CodeGenerator::GetCacheOffset(invoke->GetDexMethodIndex()));
       // LR = temp[offset_of_quick_compiled_code]
-      __ LoadFromOffset(kLoadWord, LR, temp,
-                        mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
-                            kArmWordSize).Int32Value());
+      __ LoadFromOffset(kLoadWord, LR, temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+          kArmWordSize).Int32Value());
       // LR()
       __ blx(LR);
     } else {
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 071bbee..d649cbf 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -54,7 +54,8 @@
       : CallingConvention(kRuntimeParameterCoreRegisters,
                           kRuntimeParameterCoreRegistersLength,
                           kRuntimeParameterFpuRegisters,
-                          kRuntimeParameterFpuRegistersLength) {}
+                          kRuntimeParameterFpuRegistersLength,
+                          kArmPointerSize) {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
@@ -72,7 +73,8 @@
       : CallingConvention(kParameterCoreRegisters,
                           kParameterCoreRegistersLength,
                           kParameterFpuRegisters,
-                          kParameterFpuRegistersLength) {}
+                          kParameterFpuRegistersLength,
+                          kArmPointerSize) {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index cf5a8fb..fbe26b0 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -17,6 +17,7 @@
 #include "code_generator_arm64.h"
 
 #include "arch/arm64/instruction_set_features_arm64.h"
+#include "art_method.h"
 #include "code_generator_utils.h"
 #include "common_arm64.h"
 #include "entrypoints/quick/quick_entrypoints.h"
@@ -25,8 +26,7 @@
 #include "intrinsics.h"
 #include "intrinsics_arm64.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method.h"
-#include "mirror/class.h"
+#include "mirror/class-inl.h"
 #include "offsets.h"
 #include "thread.h"
 #include "utils/arm64/assembler_arm64.h"
@@ -67,7 +67,6 @@
 using helpers::ARM64EncodableConstantOrRegister;
 using helpers::ArtVixlRegCodeCoherentForRegSet;
 
-static constexpr size_t kHeapRefSize = sizeof(mirror::HeapReference<mirror::Object>);
 static constexpr int kCurrentMethodStackOffset = 0;
 
 inline Condition ARM64Condition(IfCondition cond) {
@@ -1069,7 +1068,7 @@
 
 void CodeGeneratorARM64::LoadCurrentMethod(vixl::Register current_method) {
   DCHECK(RequiresCurrentMethod());
-  DCHECK(current_method.IsW());
+  CHECK(current_method.IsX());
   __ Ldr(current_method, MemOperand(sp, kCurrentMethodStackOffset));
 }
 
@@ -2186,12 +2185,12 @@
 
 void InstructionCodeGeneratorARM64::VisitInvokeInterface(HInvokeInterface* invoke) {
   // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError.
-  Register temp = WRegisterFrom(invoke->GetLocations()->GetTemp(0));
-  uint32_t method_offset = mirror::Class::EmbeddedImTableOffset().Uint32Value() +
-          (invoke->GetImtIndex() % mirror::Class::kImtSize) * sizeof(mirror::Class::ImTableEntry);
+  Register temp = XRegisterFrom(invoke->GetLocations()->GetTemp(0));
+  uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset(
+      invoke->GetImtIndex() % mirror::Class::kImtSize, kArm64PointerSize).Uint32Value();
   Location receiver = invoke->GetLocations()->InAt(0);
   Offset class_offset = mirror::Object::ClassOffset();
-  Offset entry_point = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize);
+  Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize);
 
   // The register ip1 is required to be used for the hidden argument in
   // art_quick_imt_conflict_trampoline, so prevent VIXL from using it.
@@ -2203,16 +2202,16 @@
 
   // temp = object->GetClass();
   if (receiver.IsStackSlot()) {
-    __ Ldr(temp, StackOperandFrom(receiver));
-    __ Ldr(temp, HeapOperand(temp, class_offset));
+    __ Ldr(temp.W(), StackOperandFrom(receiver));
+    __ Ldr(temp.W(), HeapOperand(temp.W(), class_offset));
   } else {
-    __ Ldr(temp, HeapOperandFrom(receiver, class_offset));
+    __ Ldr(temp.W(), HeapOperandFrom(receiver, class_offset));
   }
   codegen_->MaybeRecordImplicitNullCheck(invoke);
   // temp = temp->GetImtEntryAt(method_offset);
-  __ Ldr(temp, HeapOperand(temp, method_offset));
+  __ Ldr(temp, MemOperand(temp, method_offset));
   // lr = temp->GetEntryPoint();
-  __ Ldr(lr, HeapOperand(temp, entry_point));
+  __ Ldr(lr, MemOperand(temp, entry_point.Int32Value()));
   // lr();
   __ Blr(lr);
   DCHECK(!codegen_->IsLeafMethod());
@@ -2253,8 +2252,7 @@
 void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp) {
   // Make sure that ArtMethod* is passed in kArtMethodRegister as per the calling convention.
   DCHECK(temp.Is(kArtMethodRegister));
-  size_t index_in_cache = mirror::Array::DataOffset(kHeapRefSize).SizeValue() +
-      invoke->GetDexMethodIndex() * kHeapRefSize;
+  size_t index_in_cache = GetCachePointerOffset(invoke->GetDexMethodIndex());
 
   // TODO: Implement all kinds of calls:
   // 1) boot -> boot
@@ -2265,23 +2263,24 @@
 
   if (invoke->IsStringInit()) {
     // temp = thread->string_init_entrypoint
-    __ Ldr(temp, HeapOperand(tr, invoke->GetStringInitOffset()));
+    __ Ldr(temp.X(), MemOperand(tr, invoke->GetStringInitOffset()));
     // LR = temp->entry_point_from_quick_compiled_code_;
-    __ Ldr(lr, HeapOperand(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
-        kArm64WordSize)));
+    __ Ldr(lr, MemOperand(
+        temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize).Int32Value()));
     // lr()
     __ Blr(lr);
   } else {
     // temp = method;
-    LoadCurrentMethod(temp);
+    LoadCurrentMethod(temp.X());
     if (!invoke->IsRecursive()) {
       // temp = temp->dex_cache_resolved_methods_;
-      __ Ldr(temp, HeapOperand(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset()));
+      __ Ldr(temp.W(), MemOperand(temp.X(),
+                                  ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
       // temp = temp[index_in_cache];
-      __ Ldr(temp, HeapOperand(temp, index_in_cache));
+      __ Ldr(temp.X(), MemOperand(temp, index_in_cache));
       // lr = temp->entry_point_from_quick_compiled_code_;
-      __ Ldr(lr, HeapOperand(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
-          kArm64WordSize)));
+      __ Ldr(lr, MemOperand(temp.X(), ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+          kArm64WordSize).Int32Value()));
       // lr();
       __ Blr(lr);
     } else {
@@ -2302,7 +2301,7 @@
   }
 
   BlockPoolsScope block_pools(GetVIXLAssembler());
-  Register temp = WRegisterFrom(invoke->GetLocations()->GetTemp(0));
+  Register temp = XRegisterFrom(invoke->GetLocations()->GetTemp(0));
   codegen_->GenerateStaticOrDirectCall(invoke, temp);
   codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
 }
@@ -2314,27 +2313,27 @@
 
   LocationSummary* locations = invoke->GetLocations();
   Location receiver = locations->InAt(0);
-  Register temp = WRegisterFrom(invoke->GetLocations()->GetTemp(0));
-  size_t method_offset = mirror::Class::EmbeddedVTableOffset().SizeValue() +
-    invoke->GetVTableIndex() * sizeof(mirror::Class::VTableEntry);
+  Register temp = XRegisterFrom(invoke->GetLocations()->GetTemp(0));
+  size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
+      invoke->GetVTableIndex(), kArm64PointerSize).SizeValue();
   Offset class_offset = mirror::Object::ClassOffset();
-  Offset entry_point = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize);
+  Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize);
 
   BlockPoolsScope block_pools(GetVIXLAssembler());
 
   // temp = object->GetClass();
   if (receiver.IsStackSlot()) {
-    __ Ldr(temp, MemOperand(sp, receiver.GetStackIndex()));
-    __ Ldr(temp, HeapOperand(temp, class_offset));
+    __ Ldr(temp.W(), MemOperand(sp, receiver.GetStackIndex()));
+    __ Ldr(temp.W(), HeapOperand(temp.W(), class_offset));
   } else {
     DCHECK(receiver.IsRegister());
-    __ Ldr(temp, HeapOperandFrom(receiver, class_offset));
+    __ Ldr(temp.W(), HeapOperandFrom(receiver, class_offset));
   }
   codegen_->MaybeRecordImplicitNullCheck(invoke);
   // temp = temp->GetMethodAt(method_offset);
-  __ Ldr(temp, HeapOperand(temp, method_offset));
+  __ Ldr(temp, MemOperand(temp, method_offset));
   // lr = temp->GetEntryPoint();
-  __ Ldr(lr, HeapOperand(temp, entry_point.SizeValue()));
+  __ Ldr(lr, MemOperand(temp, entry_point.SizeValue()));
   // lr();
   __ Blr(lr);
   DCHECK(!codegen_->IsLeafMethod());
@@ -2355,10 +2354,10 @@
   if (cls->IsReferrersClass()) {
     DCHECK(!cls->CanCallRuntime());
     DCHECK(!cls->MustGenerateClinitCheck());
-    __ Ldr(out, HeapOperand(current_method, mirror::ArtMethod::DeclaringClassOffset()));
+    __ Ldr(out, MemOperand(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
   } else {
     DCHECK(cls->CanCallRuntime());
-    __ Ldr(out, HeapOperand(current_method, mirror::ArtMethod::DexCacheResolvedTypesOffset()));
+    __ Ldr(out, MemOperand(current_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value()));
     __ Ldr(out, HeapOperand(out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex())));
 
     SlowPathCodeARM64* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM64(
@@ -2407,7 +2406,7 @@
 
   Register out = OutputRegister(load);
   Register current_method = InputRegisterAt(load, 0);
-  __ Ldr(out, HeapOperand(current_method, mirror::ArtMethod::DeclaringClassOffset()));
+  __ Ldr(out, MemOperand(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
   __ Ldr(out, HeapOperand(out, mirror::Class::DexCacheStringsOffset()));
   __ Ldr(out, HeapOperand(out, CodeGenerator::GetCacheOffset(load->GetStringIndex())));
   __ Cbz(out, slow_path->GetEntryLabel());
@@ -2535,7 +2534,7 @@
   locations->SetOut(LocationFrom(x0));
   locations->SetInAt(0, LocationFrom(calling_convention.GetRegisterAt(1)));
   CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck,
-                       void*, uint32_t, int32_t, mirror::ArtMethod*>();
+                       void*, uint32_t, int32_t, ArtMethod*>();
 }
 
 void InstructionCodeGeneratorARM64::VisitNewArray(HNewArray* instruction) {
@@ -2543,17 +2542,16 @@
   InvokeRuntimeCallingConvention calling_convention;
   Register type_index = RegisterFrom(locations->GetTemp(0), Primitive::kPrimInt);
   DCHECK(type_index.Is(w0));
-  Register current_method = RegisterFrom(locations->GetTemp(1), Primitive::kPrimNot);
-  DCHECK(current_method.Is(w2));
-  codegen_->LoadCurrentMethod(current_method);
+  Register current_method = RegisterFrom(locations->GetTemp(1), Primitive::kPrimLong);
+  DCHECK(current_method.Is(x2));
+  codegen_->LoadCurrentMethod(current_method.X());
   __ Mov(type_index, instruction->GetTypeIndex());
   codegen_->InvokeRuntime(
       GetThreadOffset<kArm64WordSize>(instruction->GetEntrypoint()).Int32Value(),
       instruction,
       instruction->GetDexPc(),
       nullptr);
-  CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck,
-                       void*, uint32_t, int32_t, mirror::ArtMethod*>();
+  CheckEntrypointTypes<kQuickAllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*>();
 }
 
 void LocationsBuilderARM64::VisitNewInstance(HNewInstance* instruction) {
@@ -2563,7 +2561,7 @@
   locations->AddTemp(LocationFrom(calling_convention.GetRegisterAt(0)));
   locations->AddTemp(LocationFrom(calling_convention.GetRegisterAt(1)));
   locations->SetOut(calling_convention.GetReturnLocation(Primitive::kPrimNot));
-  CheckEntrypointTypes<kQuickAllocObjectWithAccessCheck, void*, uint32_t, mirror::ArtMethod*>();
+  CheckEntrypointTypes<kQuickAllocObjectWithAccessCheck, void*, uint32_t, ArtMethod*>();
 }
 
 void InstructionCodeGeneratorARM64::VisitNewInstance(HNewInstance* instruction) {
@@ -2572,14 +2570,14 @@
   DCHECK(type_index.Is(w0));
   Register current_method = RegisterFrom(locations->GetTemp(1), Primitive::kPrimNot);
   DCHECK(current_method.Is(w1));
-  codegen_->LoadCurrentMethod(current_method);
+  codegen_->LoadCurrentMethod(current_method.X());
   __ Mov(type_index, instruction->GetTypeIndex());
   codegen_->InvokeRuntime(
       GetThreadOffset<kArm64WordSize>(instruction->GetEntrypoint()).Int32Value(),
       instruction,
       instruction->GetDexPc(),
       nullptr);
-  CheckEntrypointTypes<kQuickAllocObjectWithAccessCheck, void*, uint32_t, mirror::ArtMethod*>();
+  CheckEntrypointTypes<kQuickAllocObjectWithAccessCheck, void*, uint32_t, ArtMethod*>();
 }
 
 void LocationsBuilderARM64::VisitNot(HNot* instruction) {
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index ab793a5..7a502e0 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -45,7 +45,7 @@
 static constexpr size_t kParameterFPRegistersLength = arraysize(kParameterFPRegisters);
 
 const vixl::Register tr = vixl::x19;                        // Thread Register
-static const vixl::Register kArtMethodRegister = vixl::w0;  // Method register on invoke.
+static const vixl::Register kArtMethodRegister = vixl::x0;  // Method register on invoke.
 
 const vixl::CPURegList vixl_reserved_core_registers(vixl::ip0, vixl::ip1);
 const vixl::CPURegList vixl_reserved_fp_registers(vixl::d31);
@@ -97,7 +97,8 @@
       : CallingConvention(kRuntimeParameterCoreRegisters,
                           kRuntimeParameterCoreRegistersLength,
                           kRuntimeParameterFpuRegisters,
-                          kRuntimeParameterFpuRegistersLength) {}
+                          kRuntimeParameterFpuRegistersLength,
+                          kArm64PointerSize) {}
 
   Location GetReturnLocation(Primitive::Type return_type);
 
@@ -111,7 +112,8 @@
       : CallingConvention(kParameterCoreRegisters,
                           kParameterCoreRegistersLength,
                           kParameterFPRegisters,
-                          kParameterFPRegistersLength) {}
+                          kParameterFPRegistersLength,
+                          kArm64PointerSize) {}
 
   Location GetReturnLocation(Primitive::Type return_type) {
     return ARM64ReturnLocation(return_type);
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 81c3526..8678428 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -16,6 +16,7 @@
 
 #include "code_generator_x86.h"
 
+#include "art_method.h"
 #include "code_generator_utils.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "entrypoints/quick/quick_entrypoints_enum.h"
@@ -23,8 +24,7 @@
 #include "intrinsics.h"
 #include "intrinsics_x86.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method.h"
-#include "mirror/class.h"
+#include "mirror/class-inl.h"
 #include "thread.h"
 #include "utils/assembler.h"
 #include "utils/stack_checks.h"
@@ -1276,8 +1276,8 @@
 
 void InstructionCodeGeneratorX86::VisitInvokeVirtual(HInvokeVirtual* invoke) {
   Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
-  uint32_t method_offset = mirror::Class::EmbeddedVTableOffset().Uint32Value() +
-          invoke->GetVTableIndex() * sizeof(mirror::Class::VTableEntry);
+  uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
+      invoke->GetVTableIndex(), kX86PointerSize).Uint32Value();
   LocationSummary* locations = invoke->GetLocations();
   Location receiver = locations->InAt(0);
   uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
@@ -1293,7 +1293,7 @@
   __ movl(temp, Address(temp, method_offset));
   // call temp->GetEntryPoint();
   __ call(Address(
-      temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
+      temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
 
   DCHECK(!codegen_->IsLeafMethod());
   codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
@@ -1308,8 +1308,8 @@
 void InstructionCodeGeneratorX86::VisitInvokeInterface(HInvokeInterface* invoke) {
   // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError.
   Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
-  uint32_t method_offset = mirror::Class::EmbeddedImTableOffset().Uint32Value() +
-          (invoke->GetImtIndex() % mirror::Class::kImtSize) * sizeof(mirror::Class::ImTableEntry);
+  uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset(
+      invoke->GetImtIndex() % mirror::Class::kImtSize, kX86PointerSize).Uint32Value();
   LocationSummary* locations = invoke->GetLocations();
   Location receiver = locations->InAt(0);
   uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
@@ -1329,7 +1329,7 @@
   // temp = temp->GetImtEntryAt(method_offset);
   __ movl(temp, Address(temp, method_offset));
   // call temp->GetEntryPoint();
-  __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+  __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
       kX86WordSize).Int32Value()));
 
   DCHECK(!codegen_->IsLeafMethod());
@@ -3219,18 +3219,19 @@
     __ fs()->movl(temp, Address::Absolute(invoke->GetStringInitOffset()));
     // (temp + offset_of_quick_compiled_code)()
     __ call(Address(
-        temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
+        temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
   } else {
     // temp = method;
     LoadCurrentMethod(temp);
     if (!invoke->IsRecursive()) {
       // temp = temp->dex_cache_resolved_methods_;
-      __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
+      __ movl(temp, Address(temp, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
       // temp = temp[index_in_cache]
-      __ movl(temp, Address(temp, CodeGenerator::GetCacheOffset(invoke->GetDexMethodIndex())));
+      __ movl(temp, Address(temp,
+                            CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
       // (temp + offset_of_quick_compiled_code)()
       __ call(Address(temp,
-          mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
+          ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
     } else {
       __ call(GetFrameEntryLabel());
     }
@@ -4302,11 +4303,11 @@
   if (cls->IsReferrersClass()) {
     DCHECK(!cls->CanCallRuntime());
     DCHECK(!cls->MustGenerateClinitCheck());
-    __ movl(out, Address(current_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value()));
+    __ movl(out, Address(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
   } else {
     DCHECK(cls->CanCallRuntime());
     __ movl(out, Address(
-        current_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value()));
+        current_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value()));
     __ movl(out, Address(out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex())));
 
     SlowPathCodeX86* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathX86(
@@ -4363,7 +4364,7 @@
   LocationSummary* locations = load->GetLocations();
   Register out = locations->Out().AsRegister<Register>();
   Register current_method = locations->InAt(0).AsRegister<Register>();
-  __ movl(out, Address(current_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value()));
+  __ movl(out, Address(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
   __ movl(out, Address(out, mirror::Class::DexCacheStringsOffset().Int32Value()));
   __ movl(out, Address(out, CodeGenerator::GetCacheOffset(load->GetStringIndex())));
   __ testl(out, out);
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 28766d8..6988803 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -52,7 +52,8 @@
       : CallingConvention(kRuntimeParameterCoreRegisters,
                           kRuntimeParameterCoreRegistersLength,
                           kRuntimeParameterFpuRegisters,
-                          kRuntimeParameterFpuRegistersLength) {}
+                          kRuntimeParameterFpuRegistersLength,
+                          kX86PointerSize) {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
@@ -64,7 +65,8 @@
       kParameterCoreRegisters,
       kParameterCoreRegistersLength,
       kParameterFpuRegisters,
-      kParameterFpuRegistersLength) {}
+      kParameterFpuRegistersLength,
+      kX86PointerSize) {}
 
   RegisterPair GetRegisterPairAt(size_t argument_index) {
     DCHECK_LT(argument_index + 1, GetNumberOfRegisters());
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index f8125c6..59a9565 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -16,14 +16,14 @@
 
 #include "code_generator_x86_64.h"
 
+#include "art_method.h"
 #include "code_generator_utils.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "gc/accounting/card_table.h"
 #include "intrinsics.h"
 #include "intrinsics_x86_64.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method.h"
-#include "mirror/class.h"
+#include "mirror/class-inl.h"
 #include "mirror/object_reference.h"
 #include "thread.h"
 #include "utils/assembler.h"
@@ -374,18 +374,19 @@
     // temp = thread->string_init_entrypoint
     __ gs()->movl(temp, Address::Absolute(invoke->GetStringInitOffset()));
     // (temp + offset_of_quick_compiled_code)()
-    __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+    __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
         kX86_64WordSize).SizeValue()));
   } else {
     // temp = method;
     LoadCurrentMethod(temp);
     if (!invoke->IsRecursive()) {
       // temp = temp->dex_cache_resolved_methods_;
-      __ movl(temp, Address(temp, mirror::ArtMethod::DexCacheResolvedMethodsOffset().SizeValue()));
+      __ movl(temp, Address(temp, ArtMethod::DexCacheResolvedMethodsOffset().SizeValue()));
       // temp = temp[index_in_cache]
-      __ movl(temp, Address(temp, CodeGenerator::GetCacheOffset(invoke->GetDexMethodIndex())));
+      __ movq(temp, Address(
+          temp, CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
       // (temp + offset_of_quick_compiled_code)()
-      __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+      __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
           kX86_64WordSize).SizeValue()));
     } else {
       __ call(&frame_entry_label_);
@@ -545,7 +546,7 @@
     }
   }
 
-  __ movl(Address(CpuRegister(RSP), kCurrentMethodStackOffset),
+  __ movq(Address(CpuRegister(RSP), kCurrentMethodStackOffset),
           CpuRegister(kMethodRegisterArgument));
 }
 
@@ -586,7 +587,7 @@
 
 void CodeGeneratorX86_64::LoadCurrentMethod(CpuRegister reg) {
   DCHECK(RequiresCurrentMethod());
-  __ movl(reg, Address(CpuRegister(RSP), kCurrentMethodStackOffset));
+  __ movq(reg, Address(CpuRegister(RSP), kCurrentMethodStackOffset));
 }
 
 Location CodeGeneratorX86_64::GetStackLocation(HLoadLocal* load) const {
@@ -1384,8 +1385,8 @@
   }
 
   CpuRegister temp = invoke->GetLocations()->GetTemp(0).AsRegister<CpuRegister>();
-  size_t method_offset = mirror::Class::EmbeddedVTableOffset().SizeValue() +
-          invoke->GetVTableIndex() * sizeof(mirror::Class::VTableEntry);
+  size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
+      invoke->GetVTableIndex(), kX86_64PointerSize).SizeValue();
   LocationSummary* locations = invoke->GetLocations();
   Location receiver = locations->InAt(0);
   size_t class_offset = mirror::Object::ClassOffset().SizeValue();
@@ -1398,9 +1399,9 @@
   }
   codegen_->MaybeRecordImplicitNullCheck(invoke);
   // temp = temp->GetMethodAt(method_offset);
-  __ movl(temp, Address(temp, method_offset));
+  __ movq(temp, Address(temp, method_offset));
   // call temp->GetEntryPoint();
-  __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+  __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
       kX86_64WordSize).SizeValue()));
 
   DCHECK(!codegen_->IsLeafMethod());
@@ -1416,8 +1417,8 @@
 void InstructionCodeGeneratorX86_64::VisitInvokeInterface(HInvokeInterface* invoke) {
   // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError.
   CpuRegister temp = invoke->GetLocations()->GetTemp(0).AsRegister<CpuRegister>();
-  uint32_t method_offset = mirror::Class::EmbeddedImTableOffset().Uint32Value() +
-          (invoke->GetImtIndex() % mirror::Class::kImtSize) * sizeof(mirror::Class::ImTableEntry);
+  uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset(
+      invoke->GetImtIndex() % mirror::Class::kImtSize, kX86_64PointerSize).Uint32Value();
   LocationSummary* locations = invoke->GetLocations();
   Location receiver = locations->InAt(0);
   size_t class_offset = mirror::Object::ClassOffset().SizeValue();
@@ -1435,9 +1436,9 @@
   }
   codegen_->MaybeRecordImplicitNullCheck(invoke);
   // temp = temp->GetImtEntryAt(method_offset);
-  __ movl(temp, Address(temp, method_offset));
+  __ movq(temp, Address(temp, method_offset));
   // call temp->GetEntryPoint();
-  __ call(Address(temp, mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+  __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
       kX86_64WordSize).SizeValue()));
 
   DCHECK(!codegen_->IsLeafMethod());
@@ -4150,11 +4151,11 @@
   if (cls->IsReferrersClass()) {
     DCHECK(!cls->CanCallRuntime());
     DCHECK(!cls->MustGenerateClinitCheck());
-    __ movl(out, Address(current_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value()));
+    __ movl(out, Address(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
   } else {
     DCHECK(cls->CanCallRuntime());
     __ movl(out, Address(
-        current_method, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value()));
+        current_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value()));
     __ movl(out, Address(out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex())));
     SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathX86_64(
         cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck());
@@ -4201,7 +4202,7 @@
   LocationSummary* locations = load->GetLocations();
   CpuRegister out = locations->Out().AsRegister<CpuRegister>();
   CpuRegister current_method = locations->InAt(0).AsRegister<CpuRegister>();
-  __ movl(out, Address(current_method, mirror::ArtMethod::DeclaringClassOffset().Int32Value()));
+  __ movl(out, Address(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
   __ movl(out, Address(out, mirror::Class::DexCacheStringsOffset().Int32Value()));
   __ movl(out, Address(out, CodeGenerator::GetCacheOffset(load->GetStringIndex())));
   __ testl(out, out);
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index d7bd525..c74335b 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -50,7 +50,8 @@
       : CallingConvention(kRuntimeParameterCoreRegisters,
                           kRuntimeParameterCoreRegistersLength,
                           kRuntimeParameterFpuRegisters,
-                          kRuntimeParameterFpuRegistersLength) {}
+                          kRuntimeParameterFpuRegistersLength,
+                          kX86_64PointerSize) {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(InvokeRuntimeCallingConvention);
@@ -62,7 +63,8 @@
       kParameterCoreRegisters,
       kParameterCoreRegistersLength,
       kParameterFloatRegisters,
-      kParameterFloatRegistersLength) {}
+      kParameterFloatRegistersLength,
+      kX86_64PointerSize) {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConvention);
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 15f3deb..83f8d83 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -16,6 +16,7 @@
 
 #include "inliner.h"
 
+#include "art_method-inl.h"
 #include "builder.h"
 #include "class_linker.h"
 #include "constant_folding.h"
@@ -23,7 +24,6 @@
 #include "driver/compiler_driver-inl.h"
 #include "driver/dex_compilation_unit.h"
 #include "instruction_simplifier.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/dex_cache.h"
 #include "nodes.h"
@@ -88,11 +88,10 @@
       hs.NewHandle(caller_compilation_unit_.GetClassLinker()->FindDexCache(caller_dex_file)));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
       soa.Decode<mirror::ClassLoader*>(caller_compilation_unit_.GetClassLoader())));
-  Handle<mirror::ArtMethod> resolved_method(hs.NewHandle(
-      compiler_driver_->ResolveMethod(
-          soa, dex_cache, class_loader, &caller_compilation_unit_, method_index, invoke_type)));
+  ArtMethod* resolved_method(compiler_driver_->ResolveMethod(
+      soa, dex_cache, class_loader, &caller_compilation_unit_, method_index, invoke_type));
 
-  if (resolved_method.Get() == nullptr) {
+  if (resolved_method == nullptr) {
     VLOG(compiler) << "Method cannot be resolved " << PrettyMethod(method_index, caller_dex_file);
     return false;
   }
@@ -156,7 +155,7 @@
   return true;
 }
 
-bool HInliner::TryBuildAndInline(Handle<mirror::ArtMethod> resolved_method,
+bool HInliner::TryBuildAndInline(ArtMethod* resolved_method,
                                  HInvoke* invoke_instruction,
                                  uint32_t method_index,
                                  bool same_dex_file) const {
@@ -199,6 +198,7 @@
       caller_dex_file,
       method_index,
       requires_ctor_barrier,
+      compiler_driver_->GetInstructionSet(),
       invoke_instruction->GetOriginalInvokeType(),
       graph_->IsDebuggable(),
       graph_->GetCurrentInstructionId());
diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h
index 09a36c6..b86c1ed 100644
--- a/compiler/optimizing/inliner.h
+++ b/compiler/optimizing/inliner.h
@@ -48,7 +48,7 @@
 
  private:
   bool TryInline(HInvoke* invoke_instruction, uint32_t method_index, InvokeType invoke_type) const;
-  bool TryBuildAndInline(Handle<mirror::ArtMethod> resolved_method,
+  bool TryBuildAndInline(ArtMethod* resolved_method,
                          HInvoke* invoke_instruction,
                          uint32_t method_index,
                          bool same_dex_file) const;
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index e785bf9..5436ec2 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -17,11 +17,11 @@
 #include "intrinsics_arm.h"
 
 #include "arch/arm/instruction_set_features_arm.h"
+#include "art_method.h"
 #include "code_generator_arm.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "intrinsics.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method.h"
 #include "mirror/string.h"
 #include "thread.h"
 #include "utils/arm/assembler_arm.h"
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 53497b6..d1dc5b3 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -17,12 +17,12 @@
 #include "intrinsics_arm64.h"
 
 #include "arch/arm64/instruction_set_features_arm64.h"
+#include "art_method.h"
 #include "code_generator_arm64.h"
 #include "common_arm64.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "intrinsics.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method.h"
 #include "mirror/string.h"
 #include "thread.h"
 #include "utils/arm64/assembler_arm64.h"
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index d2ca42d..5bbbc72 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -19,11 +19,11 @@
 #include <limits>
 
 #include "arch/x86/instruction_set_features_x86.h"
+#include "art_method.h"
 #include "code_generator_x86.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "intrinsics.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method.h"
 #include "mirror/string.h"
 #include "thread.h"
 #include "utils/x86/assembler_x86.h"
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 2ccecfe..d6c90ff 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -19,11 +19,11 @@
 #include <limits>
 
 #include "arch/x86_64/instruction_set_features_x86_64.h"
+#include "art_method-inl.h"
 #include "code_generator_x86_64.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "intrinsics.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method.h"
 #include "mirror/string.h"
 #include "thread.h"
 #include "utils/x86_64/assembler_x86_64.h"
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 06f6a7f..cd91d2c 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -297,7 +297,8 @@
 
 HCurrentMethod* HGraph::GetCurrentMethod() {
   if (cached_current_method_ == nullptr) {
-    cached_current_method_ = new (arena_) HCurrentMethod();
+    cached_current_method_ = new (arena_) HCurrentMethod(
+        Is64BitInstructionSet(instruction_set_) ? Primitive::kPrimLong : Primitive::kPrimInt);
     if (entry_block_->GetFirstInstruction() == nullptr) {
       entry_block_->AddInstruction(cached_current_method_);
     } else {
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 6c2506e..6c8098b 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -126,6 +126,7 @@
          const DexFile& dex_file,
          uint32_t method_idx,
          bool should_generate_constructor_barrier,
+         InstructionSet instruction_set,
          InvokeType invoke_type = kInvalidInvokeType,
          bool debuggable = false,
          int start_instruction_id = 0)
@@ -147,6 +148,7 @@
         invoke_type_(invoke_type),
         in_ssa_form_(false),
         should_generate_constructor_barrier_(should_generate_constructor_barrier),
+        instruction_set_(instruction_set),
         cached_null_constant_(nullptr),
         cached_int_constants_(std::less<int32_t>(), arena->Adapter()),
         cached_float_constants_(std::less<int32_t>(), arena->Adapter()),
@@ -399,6 +401,8 @@
 
   const bool should_generate_constructor_barrier_;
 
+  const InstructionSet instruction_set_;
+
   // Cached constants.
   HNullConstant* cached_null_constant_;
   ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
@@ -1873,7 +1877,7 @@
 // instructions that work with the dex cache.
 class HCurrentMethod : public HExpression<0> {
  public:
-  HCurrentMethod() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
+  explicit HCurrentMethod(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
 
   DECLARE_INSTRUCTION(CurrentMethod);
 
diff --git a/compiler/optimizing/optimizing_cfi_test.cc b/compiler/optimizing/optimizing_cfi_test.cc
index 7aea249..b0d1433 100644
--- a/compiler/optimizing/optimizing_cfi_test.cc
+++ b/compiler/optimizing/optimizing_cfi_test.cc
@@ -31,7 +31,7 @@
 // Run the tests only on host.
 #ifndef HAVE_ANDROID_OS
 
-class OptimizingCFITest  : public CFITest {
+class OptimizingCFITest : public CFITest {
  public:
   // Enable this flag to generate the expected outputs.
   static constexpr bool kGenerateExpected = false;
diff --git a/compiler/optimizing/optimizing_cfi_test_expected.inc b/compiler/optimizing/optimizing_cfi_test_expected.inc
index ecb3b0a..2c2c55f 100644
--- a/compiler/optimizing/optimizing_cfi_test_expected.inc
+++ b/compiler/optimizing/optimizing_cfi_test_expected.inc
@@ -32,7 +32,7 @@
 // 0x00000012: .cfi_def_cfa_offset: 64
 
 static constexpr uint8_t expected_asm_kArm64[] = {
-    0xE0, 0x0F, 0x1C, 0xB8, 0xF4, 0xD7, 0x02, 0xA9, 0xFE, 0x1F, 0x00, 0xF9,
+    0xE0, 0x0F, 0x1C, 0xF8, 0xF4, 0xD7, 0x02, 0xA9, 0xFE, 0x1F, 0x00, 0xF9,
     0xE8, 0xA7, 0x01, 0x6D, 0xE8, 0xA7, 0x41, 0x6D, 0xF4, 0xD7, 0x42, 0xA9,
     0xFE, 0x1F, 0x40, 0xF9, 0xFF, 0x03, 0x01, 0x91, 0xC0, 0x03, 0x5F, 0xD6,
 };
@@ -41,7 +41,7 @@
     0x05, 0x48, 0x0A, 0x05, 0x49, 0x08, 0x0A, 0x44, 0x06, 0x48, 0x06, 0x49,
     0x44, 0xD4, 0xD5, 0x44, 0xDE, 0x44, 0x0E, 0x00, 0x44, 0x0B, 0x0E, 0x40,
 };
-// 0x00000000: str w0, [sp, #-64]!
+// 0x00000000: str x0, [sp, #-64]!
 // 0x00000004: .cfi_def_cfa_offset: 64
 // 0x00000004: stp x20, x21, [sp, #40]
 // 0x00000008: .cfi_offset: r20 at cfa-24
@@ -99,13 +99,13 @@
 
 static constexpr uint8_t expected_asm_kX86_64[] = {
     0x55, 0x53, 0x48, 0x83, 0xEC, 0x28, 0xF2, 0x44, 0x0F, 0x11, 0x6C, 0x24,
-    0x20, 0xF2, 0x44, 0x0F, 0x11, 0x64, 0x24, 0x18, 0x89, 0x3C, 0x24, 0xF2,
-    0x44, 0x0F, 0x10, 0x64, 0x24, 0x18, 0xF2, 0x44, 0x0F, 0x10, 0x6C, 0x24,
-    0x20, 0x48, 0x83, 0xC4, 0x28, 0x5B, 0x5D, 0xC3,
+    0x20, 0xF2, 0x44, 0x0F, 0x11, 0x64, 0x24, 0x18, 0x48, 0x89, 0x3C, 0x24,
+    0xF2, 0x44, 0x0F, 0x10, 0x64, 0x24, 0x18, 0xF2, 0x44, 0x0F, 0x10, 0x6C,
+    0x24, 0x20, 0x48, 0x83, 0xC4, 0x28, 0x5B, 0x5D, 0xC3,
 };
 static constexpr uint8_t expected_cfi_kX86_64[] = {
     0x41, 0x0E, 0x10, 0x86, 0x04, 0x41, 0x0E, 0x18, 0x83, 0x06, 0x44, 0x0E,
-    0x40, 0x47, 0x9E, 0x08, 0x47, 0x9D, 0x0A, 0x43, 0x0A, 0x47, 0xDD, 0x47,
+    0x40, 0x47, 0x9E, 0x08, 0x47, 0x9D, 0x0A, 0x44, 0x0A, 0x47, 0xDD, 0x47,
     0xDE, 0x44, 0x0E, 0x18, 0x41, 0x0E, 0x10, 0xC3, 0x41, 0x0E, 0x08, 0xC6,
     0x41, 0x0B, 0x0E, 0x40,
 };
@@ -121,21 +121,20 @@
 // 0x0000000d: .cfi_offset: r30 at cfa-32
 // 0x0000000d: movsd [rsp + 24], xmm12
 // 0x00000014: .cfi_offset: r29 at cfa-40
-// 0x00000014: mov [rsp], edi
-// 0x00000017: .cfi_remember_state
-// 0x00000017: movsd xmm12, [rsp + 24]
-// 0x0000001e: .cfi_restore: r29
-// 0x0000001e: movsd xmm13, [rsp + 32]
-// 0x00000025: .cfi_restore: r30
-// 0x00000025: addq rsp, 40
-// 0x00000029: .cfi_def_cfa_offset: 24
-// 0x00000029: pop rbx
-// 0x0000002a: .cfi_def_cfa_offset: 16
-// 0x0000002a: .cfi_restore: r3
-// 0x0000002a: pop rbp
-// 0x0000002b: .cfi_def_cfa_offset: 8
-// 0x0000002b: .cfi_restore: r6
-// 0x0000002b: ret
-// 0x0000002c: .cfi_restore_state
-// 0x0000002c: .cfi_def_cfa_offset: 64
-
+// 0x00000014: movq [rsp], rdi
+// 0x00000018: .cfi_remember_state
+// 0x00000018: movsd xmm12, [rsp + 24]
+// 0x0000001f: .cfi_restore: r29
+// 0x0000001f: movsd xmm13, [rsp + 32]
+// 0x00000026: .cfi_restore: r30
+// 0x00000026: addq rsp, 40
+// 0x0000002a: .cfi_def_cfa_offset: 24
+// 0x0000002a: pop rbx
+// 0x0000002b: .cfi_def_cfa_offset: 16
+// 0x0000002b: .cfi_restore: r3
+// 0x0000002b: pop rbp
+// 0x0000002c: .cfi_def_cfa_offset: 8
+// 0x0000002c: .cfi_restore: r6
+// 0x0000002c: ret
+// 0x0000002d: .cfi_restore_state
+// 0x0000002d: .cfi_def_cfa_offset: 64
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 3123843..f6ef2f7 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -19,6 +19,7 @@
 #include <fstream>
 #include <stdint.h>
 
+#include "art_method-inl.h"
 #include "base/arena_allocator.h"
 #include "base/dumpable.h"
 #include "base/timing_logger.h"
@@ -44,7 +45,6 @@
 #include "intrinsics.h"
 #include "licm.h"
 #include "jni/quick/jni_compiler.h"
-#include "mirror/art_method-inl.h"
 #include "nodes.h"
 #include "prepare_for_register_allocation.h"
 #include "reference_type_propagation.h"
@@ -196,7 +196,7 @@
     return ArtQuickJniCompileMethod(GetCompilerDriver(), access_flags, method_idx, dex_file);
   }
 
-  uintptr_t GetEntryPointOf(mirror::ArtMethod* method) const OVERRIDE
+  uintptr_t GetEntryPointOf(ArtMethod* method) const OVERRIDE
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return reinterpret_cast<uintptr_t>(method->GetEntryPointFromQuickCompiledCodePtrSize(
         InstructionSetPointerSize(GetCompilerDriver()->GetInstructionSet())));
@@ -515,8 +515,8 @@
                                                      dex_compilation_unit.GetClassDefIndex());
   ArenaAllocator arena(Runtime::Current()->GetArenaPool());
   HGraph* graph = new (&arena) HGraph(
-      &arena, dex_file, method_idx, requires_barrier, kInvalidInvokeType,
-      compiler_driver->GetCompilerOptions().GetDebuggable());
+      &arena, dex_file, method_idx, requires_barrier, compiler_driver->GetInstructionSet(),
+      kInvalidInvokeType, compiler_driver->GetCompilerOptions().GetDebuggable());
 
   // For testing purposes, we put a special marker on method names that should be compiled
   // with this compiler. This makes sure we're not regressing.
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index 1fe9346..86c22ed 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -74,7 +74,8 @@
 
 inline HGraph* CreateGraph(ArenaAllocator* allocator) {
   return new (allocator) HGraph(
-      allocator, *reinterpret_cast<DexFile*>(allocator->Alloc(sizeof(DexFile))), -1, false);
+      allocator, *reinterpret_cast<DexFile*>(allocator->Alloc(sizeof(DexFile))), -1, false,
+      kRuntimeISA);
 }
 
 // Create a control-flow graph from Dex instructions.
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index f7d2ed1..4f1f457 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -16,7 +16,7 @@
 
 #include "reference_type_propagation.h"
 
-#include "class_linker.h"
+#include "class_linker-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
 #include "scoped_thread_state_change.h"
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index 9a859bf..5e784d7 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -71,7 +71,9 @@
   physical_fp_register_intervals_.SetSize(codegen->GetNumberOfFloatingPointRegisters());
   // Always reserve for the current method and the graph's max out registers.
   // TODO: compute it instead.
-  reserved_out_slots_ = 1 + codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
+  // ArtMethod* takes 2 vregs for 64 bits.
+  reserved_out_slots_ = InstructionSetPointerSize(codegen->GetInstructionSet()) / kVRegSize +
+      codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
 }
 
 bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph ATTRIBUTE_UNUSED,
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index 0cd5c8b..0086fe8 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -378,7 +378,7 @@
   return dwarf::Reg::ArmFp(static_cast<int>(reg));
 }
 
-constexpr size_t kFramePointerSize = 4;
+constexpr size_t kFramePointerSize = kArmPointerSize;
 
 void ArmAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
                               const std::vector<ManagedRegister>& callee_save_regs,
@@ -415,7 +415,7 @@
   StoreToOffset(kStoreWord, R0, SP, 0);
 
   // Write out entry spills.
-  int32_t offset = frame_size + sizeof(StackReference<mirror::ArtMethod>);
+  int32_t offset = frame_size + kFramePointerSize;
   for (size_t i = 0; i < entry_spills.size(); ++i) {
     ArmManagedRegister reg = entry_spills.at(i).AsArm();
     if (reg.IsNoRegister()) {
@@ -528,13 +528,13 @@
   StoreToOffset(kStoreWord, scratch.AsCoreRegister(), SP, dest.Int32Value());
 }
 
-void ArmAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
-                           MemberOffset offs) {
+void ArmAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
+                           bool poison_reference) {
   ArmManagedRegister dst = mdest.AsArm();
   CHECK(dst.IsCoreRegister() && dst.IsCoreRegister()) << dst;
   LoadFromOffset(kLoadWord, dst.AsCoreRegister(),
                  base.AsArm().AsCoreRegister(), offs.Int32Value());
-  if (kPoisonHeapReferences) {
+  if (kPoisonHeapReferences && poison_reference) {
     rsb(dst.AsCoreRegister(), dst.AsCoreRegister(), ShifterOperand(0));
   }
 }
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index 9179965..350efca 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -711,9 +711,10 @@
 
   void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
 
-  void LoadRef(ManagedRegister dest, FrameOffset  src) OVERRIDE;
+  void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
 
-  void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
+  void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
+               bool poison_reference) OVERRIDE;
 
   void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
 
diff --git a/compiler/utils/arm64/assembler_arm64.cc b/compiler/utils/arm64/assembler_arm64.cc
index 9cc0c91..cc78002 100644
--- a/compiler/utils/arm64/assembler_arm64.cc
+++ b/compiler/utils/arm64/assembler_arm64.cc
@@ -293,14 +293,14 @@
   LoadWFromOffset(kLoadWord, dst.AsOverlappingWRegister(), SP, offs.Int32Value());
 }
 
-void Arm64Assembler::LoadRef(ManagedRegister m_dst, ManagedRegister m_base,
-                             MemberOffset offs) {
+void Arm64Assembler::LoadRef(ManagedRegister m_dst, ManagedRegister m_base, MemberOffset offs,
+                             bool poison_reference) {
   Arm64ManagedRegister dst = m_dst.AsArm64();
   Arm64ManagedRegister base = m_base.AsArm64();
   CHECK(dst.IsXRegister() && base.IsXRegister());
   LoadWFromOffset(kLoadWord, dst.AsOverlappingWRegister(), base.AsXRegister(),
                   offs.Int32Value());
-  if (kPoisonHeapReferences) {
+  if (kPoisonHeapReferences && poison_reference) {
     WRegister ref_reg = dst.AsOverlappingWRegister();
     ___ Neg(reg_w(ref_reg), vixl::Operand(reg_w(ref_reg)));
   }
@@ -535,7 +535,7 @@
   Arm64ManagedRegister scratch = m_scratch.AsArm64();
   CHECK(scratch.IsXRegister()) << scratch;
   // Call *(*(SP + base) + offset)
-  LoadWFromOffset(kLoadWord, scratch.AsOverlappingWRegister(), SP, base.Int32Value());
+  LoadFromOffset(scratch.AsXRegister(), SP, base.Int32Value());
   LoadFromOffset(scratch.AsXRegister(), scratch.AsXRegister(), offs.Int32Value());
   ___ Blr(reg_x(scratch.AsXRegister()));
 }
@@ -544,8 +544,9 @@
   UNIMPLEMENTED(FATAL) << "Unimplemented Call() variant";
 }
 
-void Arm64Assembler::CreateHandleScopeEntry(ManagedRegister m_out_reg, FrameOffset handle_scope_offs,
-                                     ManagedRegister m_in_reg, bool null_allowed) {
+void Arm64Assembler::CreateHandleScopeEntry(
+    ManagedRegister m_out_reg, FrameOffset handle_scope_offs, ManagedRegister m_in_reg,
+    bool null_allowed) {
   Arm64ManagedRegister out_reg = m_out_reg.AsArm64();
   Arm64ManagedRegister in_reg = m_in_reg.AsArm64();
   // For now we only hold stale handle scope entries in x registers.
@@ -571,7 +572,7 @@
 }
 
 void Arm64Assembler::CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handle_scope_offset,
-                                     ManagedRegister m_scratch, bool null_allowed) {
+                                            ManagedRegister m_scratch, bool null_allowed) {
   Arm64ManagedRegister scratch = m_scratch.AsArm64();
   CHECK(scratch.IsXRegister()) << scratch;
   if (null_allowed) {
@@ -590,7 +591,7 @@
 }
 
 void Arm64Assembler::LoadReferenceFromHandleScope(ManagedRegister m_out_reg,
-                                           ManagedRegister m_in_reg) {
+                                                  ManagedRegister m_in_reg) {
   Arm64ManagedRegister out_reg = m_out_reg.AsArm64();
   Arm64ManagedRegister in_reg = m_in_reg.AsArm64();
   CHECK(out_reg.IsXRegister()) << out_reg;
@@ -701,7 +702,7 @@
 
   // Increase frame to required size.
   DCHECK_ALIGNED(frame_size, kStackAlignment);
-  DCHECK_GE(frame_size, core_reg_size + fp_reg_size + sizeof(StackReference<mirror::ArtMethod>));
+  DCHECK_GE(frame_size, core_reg_size + fp_reg_size + kArm64PointerSize);
   IncreaseFrameSize(frame_size);
 
   // Save callee-saves.
@@ -710,13 +711,12 @@
 
   DCHECK(core_reg_list.IncludesAliasOf(reg_x(TR)));
 
-  // Write StackReference<Method>.
+  // Write ArtMethod*
   DCHECK(X0 == method_reg.AsArm64().AsXRegister());
-  DCHECK_EQ(4U, sizeof(StackReference<mirror::ArtMethod>));
-  StoreWToOffset(StoreOperandType::kStoreWord, W0, SP, 0);
+  StoreToOffset(X0, SP, 0);
 
   // Write out entry spills
-  int32_t offset = frame_size + sizeof(StackReference<mirror::ArtMethod>);
+  int32_t offset = frame_size + kArm64PointerSize;
   for (size_t i = 0; i < entry_spills.size(); ++i) {
     Arm64ManagedRegister reg = entry_spills.at(i).AsArm64();
     if (reg.IsNoRegister()) {
@@ -758,7 +758,7 @@
 
   // For now we only check that the size of the frame is large enough to hold spills and method
   // reference.
-  DCHECK_GE(frame_size, core_reg_size + fp_reg_size + sizeof(StackReference<mirror::ArtMethod>));
+  DCHECK_GE(frame_size, core_reg_size + fp_reg_size + kArm64PointerSize);
   DCHECK_ALIGNED(frame_size, kStackAlignment);
 
   DCHECK(core_reg_list.IncludesAliasOf(reg_x(TR)));
diff --git a/compiler/utils/arm64/assembler_arm64.h b/compiler/utils/arm64/assembler_arm64.h
index b1b66ed..fa9faed 100644
--- a/compiler/utils/arm64/assembler_arm64.h
+++ b/compiler/utils/arm64/assembler_arm64.h
@@ -113,8 +113,9 @@
   // Load routines.
   void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
   void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size) OVERRIDE;
-  void LoadRef(ManagedRegister dest, FrameOffset  src) OVERRIDE;
-  void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
+  void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
+  void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
+               bool poison_reference) OVERRIDE;
   void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
   void LoadRawPtrFromThread64(ManagedRegister dest, ThreadOffset<8> offs) OVERRIDE;
 
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h
index 2e3a47b..672e150 100644
--- a/compiler/utils/assembler.h
+++ b/compiler/utils/assembler.h
@@ -434,8 +434,10 @@
   virtual void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size);
   virtual void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size);
 
-  virtual void LoadRef(ManagedRegister dest, FrameOffset  src) = 0;
-  virtual void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) = 0;
+  virtual void LoadRef(ManagedRegister dest, FrameOffset src) = 0;
+  // If poison_reference is true and kPoisonReference is true, then we negate the read reference.
+  virtual void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
+                       bool poison_reference) = 0;
 
   virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) = 0;
 
diff --git a/compiler/utils/dex_cache_arrays_layout-inl.h b/compiler/utils/dex_cache_arrays_layout-inl.h
index a71eece..fec981a 100644
--- a/compiler/utils/dex_cache_arrays_layout-inl.h
+++ b/compiler/utils/dex_cache_arrays_layout-inl.h
@@ -25,12 +25,6 @@
 #include "mirror/array-inl.h"
 #include "primitive.h"
 
-namespace mirror {
-class ArtMethod;
-class Class;
-class String;
-}  // namespace mirror
-
 namespace art {
 
 inline DexCacheArraysLayout::DexCacheArraysLayout(size_t pointer_size, const DexFile* dex_file)
@@ -40,7 +34,7 @@
       strings_offset_(methods_offset_ + MethodsSize(dex_file->NumMethodIds())),
       fields_offset_(strings_offset_ + StringsSize(dex_file->NumStringIds())),
       size_(fields_offset_ + FieldsSize(dex_file->NumFieldIds())) {
-  DCHECK(pointer_size == 4u || pointer_size == 8u);
+  DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
 }
 
 inline size_t DexCacheArraysLayout::TypeOffset(uint32_t type_idx) const {
@@ -52,12 +46,11 @@
 }
 
 inline size_t DexCacheArraysLayout::MethodOffset(uint32_t method_idx) const {
-  return methods_offset_ + ElementOffset(
-      sizeof(mirror::HeapReference<mirror::ArtMethod>), method_idx);
+  return methods_offset_ + ElementOffset(pointer_size_, method_idx);
 }
 
 inline size_t DexCacheArraysLayout::MethodsSize(size_t num_elements) const {
-  return ArraySize(sizeof(mirror::HeapReference<mirror::ArtMethod>), num_elements);
+  return ArraySize(pointer_size_, num_elements);
 }
 
 inline size_t DexCacheArraysLayout::StringOffset(uint32_t string_idx) const {
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index e769489..e55b461 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -696,13 +696,13 @@
   LoadFromOffset(kLoadWord, dest.AsCoreRegister(), SP, src.Int32Value());
 }
 
-void MipsAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
-                            MemberOffset offs) {
+void MipsAssembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
+                            bool poison_reference) {
   MipsManagedRegister dest = mdest.AsMips();
   CHECK(dest.IsCoreRegister() && dest.IsCoreRegister());
   LoadFromOffset(kLoadWord, dest.AsCoreRegister(),
                  base.AsMips().AsCoreRegister(), offs.Int32Value());
-  if (kPoisonHeapReferences) {
+  if (kPoisonHeapReferences && poison_reference) {
     Subu(dest.AsCoreRegister(), ZERO, dest.AsCoreRegister());
   }
 }
diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h
index 34713e1..7b0fc39 100644
--- a/compiler/utils/mips/assembler_mips.h
+++ b/compiler/utils/mips/assembler_mips.h
@@ -189,9 +189,10 @@
 
   void LoadFromThread32(ManagedRegister mdest, ThreadOffset<4> src, size_t size) OVERRIDE;
 
-  void LoadRef(ManagedRegister dest, FrameOffset  src) OVERRIDE;
+  void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
 
-  void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs) OVERRIDE;
+  void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
+               bool poison_reference) OVERRIDE;
 
   void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) OVERRIDE;
 
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc
index b95e436..a8b55d1 100644
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ b/compiler/utils/mips64/assembler_mips64.cc
@@ -601,10 +601,10 @@
   }
 
   // Write out Method*.
-  StoreToOffset(kStoreWord, method_reg.AsMips64().AsGpuRegister(), SP, 0);
+  StoreToOffset(kStoreDoubleword, method_reg.AsMips64().AsGpuRegister(), SP, 0);
 
   // Write out entry spills.
-  int32_t offset = frame_size + sizeof(StackReference<mirror::ArtMethod>);
+  int32_t offset = frame_size + kFramePointerSize;
   for (size_t i = 0; i < entry_spills.size(); ++i) {
     Mips64ManagedRegister reg = entry_spills.at(i).AsMips64();
     ManagedRegisterSpill spill = entry_spills.at(i);
@@ -750,12 +750,13 @@
   LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), SP, src.Int32Value());
 }
 
-void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs) {
+void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
+                              bool poison_reference) {
   Mips64ManagedRegister dest = mdest.AsMips64();
   CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
   LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(),
                  base.AsMips64().AsGpuRegister(), offs.Int32Value());
-  if (kPoisonHeapReferences) {
+  if (kPoisonHeapReferences && poison_reference) {
     Subu(dest.AsGpuRegister(), ZERO, dest.AsGpuRegister());
   }
 }
@@ -1004,7 +1005,7 @@
   Mips64ManagedRegister scratch = mscratch.AsMips64();
   CHECK(scratch.IsGpuRegister()) << scratch;
   // Call *(*(SP + base) + offset)
-  LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(),
+  LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
                  SP, base.Int32Value());
   LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
                  scratch.AsGpuRegister(), offset.Int32Value());
diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h
index 95ba967..38419ab 100644
--- a/compiler/utils/mips64/assembler_mips64.h
+++ b/compiler/utils/mips64/assembler_mips64.h
@@ -188,9 +188,10 @@
 
   void LoadFromThread64(ManagedRegister mdest, ThreadOffset<8> src, size_t size) OVERRIDE;
 
-  void LoadRef(ManagedRegister dest, FrameOffset  src) OVERRIDE;
+  void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
 
-  void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs) OVERRIDE;
+  void LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
+               bool poison_reference) OVERRIDE;
 
   void LoadRawPtr(ManagedRegister mdest, ManagedRegister base, Offset offs) OVERRIDE;
 
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index 7e75200..390d46e 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -1724,9 +1724,9 @@
   }
 
   // return address then method on stack.
-  int32_t adjust = frame_size - (gpr_count * kFramePointerSize) -
-                   sizeof(StackReference<mirror::ArtMethod>) /*method*/ -
-                   kFramePointerSize /*return address*/;
+  int32_t adjust = frame_size - gpr_count * kFramePointerSize -
+      kFramePointerSize /*method*/ -
+      kFramePointerSize /*return address*/;
   addl(ESP, Immediate(-adjust));
   cfi_.AdjustCFAOffset(adjust);
   pushl(method_reg.AsX86().AsCpuRegister());
@@ -1750,12 +1750,11 @@
   }
 }
 
-void X86Assembler::RemoveFrame(size_t frame_size,
-                            const std::vector<ManagedRegister>& spill_regs) {
+void X86Assembler::RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& spill_regs) {
   CHECK_ALIGNED(frame_size, kStackAlignment);
   cfi_.RememberState();
-  int adjust = frame_size - (spill_regs.size() * kFramePointerSize) -
-               sizeof(StackReference<mirror::ArtMethod>);
+  // -kFramePointerSize for ArtMethod*.
+  int adjust = frame_size - spill_regs.size() * kFramePointerSize - kFramePointerSize;
   addl(ESP, Immediate(adjust));
   cfi_.AdjustCFAOffset(-adjust);
   for (size_t i = 0; i < spill_regs.size(); ++i) {
@@ -1904,18 +1903,18 @@
   }
 }
 
-void X86Assembler::LoadRef(ManagedRegister mdest, FrameOffset  src) {
+void X86Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
   X86ManagedRegister dest = mdest.AsX86();
   CHECK(dest.IsCpuRegister());
   movl(dest.AsCpuRegister(), Address(ESP, src));
 }
 
-void X86Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
-                           MemberOffset offs) {
+void X86Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
+                           bool poison_reference) {
   X86ManagedRegister dest = mdest.AsX86();
   CHECK(dest.IsCpuRegister() && dest.IsCpuRegister());
   movl(dest.AsCpuRegister(), Address(base.AsX86().AsCpuRegister(), offs));
-  if (kPoisonHeapReferences) {
+  if (kPoisonHeapReferences && poison_reference) {
     negl(dest.AsCpuRegister());
   }
 }
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 5319dac..1c1c023 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -538,9 +538,10 @@
 
   void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size) OVERRIDE;
 
-  void LoadRef(ManagedRegister dest, FrameOffset  src) OVERRIDE;
+  void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
 
-  void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
+  void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
+               bool poison_reference) OVERRIDE;
 
   void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
 
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index feceeca..ac95c71 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -2388,9 +2388,9 @@
     }
   }
 
-  DCHECK_EQ(4U, sizeof(StackReference<mirror::ArtMethod>));
+  DCHECK_EQ(kX86_64PointerSize, kFramePointerSize);
 
-  movl(Address(CpuRegister(RSP), 0), method_reg.AsX86_64().AsCpuRegister());
+  movq(Address(CpuRegister(RSP), 0), method_reg.AsX86_64().AsCpuRegister());
 
   for (size_t i = 0; i < entry_spills.size(); ++i) {
     ManagedRegisterSpill spill = entry_spills.at(i);
@@ -2590,18 +2590,18 @@
   }
 }
 
-void X86_64Assembler::LoadRef(ManagedRegister mdest, FrameOffset  src) {
+void X86_64Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
   X86_64ManagedRegister dest = mdest.AsX86_64();
   CHECK(dest.IsCpuRegister());
   movq(dest.AsCpuRegister(), Address(CpuRegister(RSP), src));
 }
 
-void X86_64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
-                           MemberOffset offs) {
+void X86_64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs,
+                              bool poison_reference) {
   X86_64ManagedRegister dest = mdest.AsX86_64();
   CHECK(dest.IsCpuRegister() && dest.IsCpuRegister());
   movl(dest.AsCpuRegister(), Address(base.AsX86_64().AsCpuRegister(), offs));
-  if (kPoisonHeapReferences) {
+  if (kPoisonHeapReferences && poison_reference) {
     negl(dest.AsCpuRegister());
   }
 }
@@ -2667,8 +2667,7 @@
   }
 }
 
-void X86_64Assembler::CopyRef(FrameOffset dest, FrameOffset src,
-                           ManagedRegister mscratch) {
+void X86_64Assembler::CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister mscratch) {
   X86_64ManagedRegister scratch = mscratch.AsX86_64();
   CHECK(scratch.IsCpuRegister());
   movl(scratch.AsCpuRegister(), Address(CpuRegister(RSP), src));
@@ -2693,9 +2692,8 @@
   gs()->movq(Address::Absolute(thr_offs, true), scratch.AsCpuRegister());
 }
 
-void X86_64Assembler::Copy(FrameOffset dest, FrameOffset src,
-                        ManagedRegister mscratch,
-                        size_t size) {
+void X86_64Assembler::Copy(FrameOffset dest, FrameOffset src, ManagedRegister mscratch,
+                           size_t size) {
   X86_64ManagedRegister scratch = mscratch.AsX86_64();
   if (scratch.IsCpuRegister() && size == 8) {
     Load(scratch, src, 4);
@@ -2834,7 +2832,7 @@
 
 void X86_64Assembler::Call(FrameOffset base, Offset offset, ManagedRegister mscratch) {
   CpuRegister scratch = mscratch.AsX86_64().AsCpuRegister();
-  movl(scratch, Address(CpuRegister(RSP), base));
+  movq(scratch, Address(CpuRegister(RSP), base));
   call(Address(scratch, offset));
 }
 
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 7daf994..6b2b65d 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -668,7 +668,8 @@
 
   void LoadRef(ManagedRegister dest, FrameOffset  src) OVERRIDE;
 
-  void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) OVERRIDE;
+  void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
+               bool poison_reference) OVERRIDE;
 
   void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
 
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index dcffe35..b86bc85 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -1127,7 +1127,7 @@
   ssize_t displacement = static_cast<ssize_t>(frame_size) - (spill_regs.size() * 8 + 8);
   str << "subq $" << displacement << ", %rsp\n";
   // 3) Store method reference.
-  str << "movl %edi, (%rsp)\n";
+  str << "movq %rdi, (%rsp)\n";
   // 4) Entry spills.
   str << "movq %rax, " << frame_size + 0 << "(%rsp)\n";
   str << "movq %rbx, " << frame_size + 8 << "(%rsp)\n";
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index cf4ef3e..d45ab1b 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -35,6 +35,7 @@
 #define ATRACE_TAG ATRACE_TAG_DALVIK
 #include <cutils/trace.h>
 
+#include "art_method-inl.h"
 #include "arch/instruction_set_features.h"
 #include "arch/mips/instruction_set_features_mips.h"
 #include "base/dumpable.h"
@@ -61,7 +62,6 @@
 #include "image_writer.h"
 #include "interpreter/unstarted_runtime.h"
 #include "leb128.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc
index 1056fe1..f324881 100644
--- a/imgdiag/imgdiag.cc
+++ b/imgdiag/imgdiag.cc
@@ -24,13 +24,13 @@
 #include <set>
 #include <map>
 
+#include "art_method-inl.h"
 #include "base/unix_file/fd_file.h"
 #include "base/stringprintf.h"
 #include "gc/space/image_space.h"
 #include "gc/heap.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
-#include "mirror/art_method-inl.h"
 #include "image.h"
 #include "scoped_thread_state_change.h"
 #include "os.h"
@@ -171,9 +171,8 @@
 
     const uint8_t* image_begin_unaligned = boot_image_header.GetImageBegin();
     const uint8_t* image_mirror_end_unaligned = image_begin_unaligned +
-        boot_image_header.GetImageSize();
-    const uint8_t* image_end_unaligned = image_mirror_end_unaligned +
-        boot_image_header.GetArtFieldsSize();
+        boot_image_header.GetImageSection(ImageHeader::kSectionObjects).Size();
+    const uint8_t* image_end_unaligned = image_begin_unaligned + boot_image_header.GetImageSize();
 
     // Adjust range to nearest page
     const uint8_t* image_begin = AlignDown(image_begin_unaligned, kPageSize);
@@ -335,7 +334,7 @@
     std::map<mirror::Class*, std::string> class_to_descriptor_map;
 
     std::map<off_t /* field offset */, int /* count */> art_method_field_dirty_count;
-    std::vector<mirror::ArtMethod*> art_method_dirty_objects;
+    std::vector<ArtMethod*> art_method_dirty_objects;
 
     std::map<off_t /* field offset */, int /* count */> class_field_dirty_count;
     std::vector<mirror::Class*> class_dirty_objects;
@@ -437,7 +436,7 @@
             class_dirty_objects.push_back(obj_as_class);
           } else if (strcmp(descriptor.c_str(), "Ljava/lang/reflect/ArtMethod;") == 0) {
             // this is an ArtMethod
-            mirror::ArtMethod* art_method = reinterpret_cast<mirror::ArtMethod*>(remote_obj);
+            ArtMethod* art_method = reinterpret_cast<ArtMethod*>(remote_obj);
 
             // print the fields that are dirty
             for (size_t i = 0; i < obj->SizeOf(); ++i) {
@@ -533,7 +532,7 @@
         const auto& dirty_objects_list = dirty_objects_by_class[klass];
         for (mirror::Object* obj : dirty_objects_list) {
           // remote method
-          auto art_method = reinterpret_cast<mirror::ArtMethod*>(obj);
+          auto art_method = reinterpret_cast<ArtMethod*>(obj);
 
           // remote class
           mirror::Class* remote_declaring_class =
@@ -551,7 +550,7 @@
                     art_method->GetEntryPointFromJniPtrSize(pointer_size)) << ", ";
           os << "  entryPointFromInterpreter: "
              << reinterpret_cast<const void*>(
-                    art_method->GetEntryPointFromInterpreterPtrSize<kVerifyNone>(pointer_size))
+                    art_method->GetEntryPointFromInterpreterPtrSize(pointer_size))
              << ", ";
           os << "  entryPointFromQuickCompiledCode: "
              << reinterpret_cast<const void*>(
@@ -623,7 +622,7 @@
         os << "      field contents:\n";
         for (mirror::Object* obj : art_method_false_dirty_objects) {
           // local method
-          auto art_method = reinterpret_cast<mirror::ArtMethod*>(obj);
+          auto art_method = reinterpret_cast<ArtMethod*>(obj);
 
           // local class
           mirror::Class* declaring_class = art_method->GetDeclaringClass();
@@ -634,7 +633,7 @@
                     art_method->GetEntryPointFromJniPtrSize(pointer_size)) << ", ";
           os << "  entryPointFromInterpreter: "
              << reinterpret_cast<const void*>(
-                    art_method->GetEntryPointFromInterpreterPtrSize<kVerifyNone>(pointer_size))
+                    art_method->GetEntryPointFromInterpreterPtrSize(pointer_size))
              << ", ";
           os << "  entryPointFromQuickCompiledCode: "
              << reinterpret_cast<const void*>(
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 04f5a6a..f13cb68 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -27,6 +27,7 @@
 
 #include "arch/instruction_set_features.h"
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
 #include "class_linker-inl.h"
@@ -41,7 +42,6 @@
 #include "image.h"
 #include "indenter.h"
 #include "mapping_table.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/array-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
@@ -64,14 +64,16 @@
 
 namespace art {
 
-const char* image_roots_descriptions_[] = {
+const char* image_methods_descriptions_[] = {
   "kResolutionMethod",
   "kImtConflictMethod",
   "kImtUnimplementedMethod",
-  "kDefaultImt",
   "kCalleeSaveMethod",
   "kRefsOnlySaveMethod",
   "kRefsAndArgsSaveMethod",
+};
+
+const char* image_roots_descriptions_[] = {
   "kDexCaches",
   "kClassRoots",
 };
@@ -494,7 +496,7 @@
     return oat_file_.GetOatHeader().GetInstructionSet();
   }
 
-  const void* GetQuickOatCode(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  const void* GetQuickOatCode(ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     for (size_t i = 0; i < oat_dex_files_.size(); i++) {
       const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
       CHECK(oat_dex_file != nullptr);
@@ -1311,12 +1313,9 @@
       Handle<mirror::DexCache> dex_cache(
           hs.NewHandle(Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file)));
       DCHECK(options_.class_loader_ != nullptr);
-      return verifier::MethodVerifier::VerifyMethodAndDump(soa.Self(), os, dex_method_idx, dex_file,
-                                                           dex_cache,
-                                                           *options_.class_loader_,
-                                                           &class_def, code_item,
-                                                           NullHandle<mirror::ArtMethod>(),
-                                                           method_access_flags);
+      return verifier::MethodVerifier::VerifyMethodAndDump(
+          soa.Self(), os, dex_method_idx, dex_file, dex_cache, *options_.class_loader_, &class_def,
+          code_item, nullptr, method_access_flags);
     }
 
     return nullptr;
@@ -1378,8 +1377,12 @@
 
     os << "IMAGE BEGIN: " << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n\n";
 
-    os << "IMAGE BITMAP OFFSET: " << reinterpret_cast<void*>(image_header_.GetImageBitmapOffset())
-       << " SIZE: " << reinterpret_cast<void*>(image_header_.GetImageBitmapSize()) << "\n\n";
+    os << "IMAGE SIZE: " << image_header_.GetImageSize() << "\n\n";
+
+    for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
+      auto section = static_cast<ImageHeader::ImageSections>(i);
+      os << "IMAGE SECTION " << section << ": " << image_header_.GetImageSection(section) << "\n\n";
+    }
 
     os << "OAT CHECKSUM: " << StringPrintf("0x%08x\n\n", image_header_.GetOatChecksum());
 
@@ -1399,7 +1402,8 @@
       os << "ROOTS: " << reinterpret_cast<void*>(image_header_.GetImageRoots()) << "\n";
       Indenter indent1_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
       std::ostream indent1_os(&indent1_filter);
-      CHECK_EQ(arraysize(image_roots_descriptions_), size_t(ImageHeader::kImageRootsMax));
+      static_assert(arraysize(image_roots_descriptions_) ==
+          static_cast<size_t>(ImageHeader::kImageRootsMax), "sizes must match");
       for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
         ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
         const char* image_root_description = image_roots_descriptions_[i];
@@ -1434,6 +1438,16 @@
           }
         }
       }
+
+      os << "METHOD ROOTS\n";
+      static_assert(arraysize(image_methods_descriptions_) ==
+          static_cast<size_t>(ImageHeader::kImageMethodsCount), "sizes must match");
+      for (int i = 0; i < ImageHeader::kImageMethodsCount; i++) {
+        auto image_root = static_cast<ImageHeader::ImageMethod>(i);
+        const char* description = image_methods_descriptions_[i];
+        auto* image_method = image_header_.GetImageMethod(image_root);
+        indent1_os << StringPrintf("%s: %p\n", description, image_method);
+      }
     }
     os << "\n";
 
@@ -1493,12 +1507,37 @@
       Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
       std::ostream indent_os(&indent_filter);
       os_ = &indent_os;
+
+      // Mark dex caches.
+      dex_cache_arrays_.clear();
+      {
+        ReaderMutexLock mu(self, *class_linker->DexLock());
+        for (size_t i = 0; i < class_linker->GetDexCacheCount(); ++i) {
+          auto* dex_cache = class_linker->GetDexCache(i);
+          dex_cache_arrays_.insert(dex_cache->GetResolvedFields());
+          dex_cache_arrays_.insert(dex_cache->GetResolvedMethods());
+        }
+      }
       ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
       for (const auto& space : spaces) {
         if (space->IsImageSpace()) {
-          gc::space::ImageSpace* image_space = space->AsImageSpace();
+          auto* image_space = space->AsImageSpace();
+          // Dump the normal objects before ArtMethods.
           image_space->GetLiveBitmap()->Walk(ImageDumper::Callback, this);
           indent_os << "\n";
+          // TODO: Dump fields.
+          // Dump methods after.
+          const auto& methods_section = image_header_.GetMethodsSection();
+          const auto pointer_size =
+              InstructionSetPointerSize(oat_dumper_->GetOatInstructionSet());
+          const auto method_size = ArtMethod::ObjectSize(pointer_size);
+          for (size_t pos = 0; pos < methods_section.Size(); pos += method_size) {
+            auto* method = reinterpret_cast<ArtMethod*>(
+                image_space->Begin() + pos + methods_section.Offset());
+            indent_os << method << " " << " ArtMethod: " << PrettyMethod(method) << "\n";
+            DumpMethod(method, this, indent_os);
+            indent_os << "\n";
+          }
         }
       }
       // Dump the large objects separately.
@@ -1515,11 +1554,16 @@
       stats_.file_bytes = file->GetLength();
     }
     size_t header_bytes = sizeof(ImageHeader);
+    const auto& bitmap_section = image_header_.GetImageSection(ImageHeader::kSectionImageBitmap);
+    const auto& field_section = image_header_.GetImageSection(ImageHeader::kSectionArtFields);
+    const auto& method_section = image_header_.GetMethodsSection();
     stats_.header_bytes = header_bytes;
     size_t alignment_bytes = RoundUp(header_bytes, kObjectAlignment) - header_bytes;
     stats_.alignment_bytes += alignment_bytes;
-    stats_.alignment_bytes += image_header_.GetImageBitmapOffset() - image_header_.GetImageSize();
-    stats_.bitmap_bytes += image_header_.GetImageBitmapSize();
+    stats_.alignment_bytes += bitmap_section.Offset() - image_header_.GetImageSize();
+    stats_.bitmap_bytes += bitmap_section.Size();
+    stats_.art_field_bytes += field_section.Size();
+    stats_.art_method_bytes += method_section.Size();
     stats_.Dump(os);
     os << "\n";
 
@@ -1541,9 +1585,6 @@
     } else if (type->IsClassClass()) {
       mirror::Class* klass = value->AsClass();
       os << StringPrintf("%p   Class: %s\n", klass, PrettyDescriptor(klass).c_str());
-    } else if (type->IsArtMethodClass()) {
-      mirror::ArtMethod* method = value->AsArtMethod();
-      os << StringPrintf("%p   Method: %s\n", method, PrettyMethod(method).c_str());
     } else {
       os << StringPrintf("%p   %s\n", value, PrettyDescriptor(type).c_str());
     }
@@ -1618,7 +1659,7 @@
     return image_space_.Contains(object);
   }
 
-  const void* GetQuickOatCodeBegin(mirror::ArtMethod* m)
+  const void* GetQuickOatCodeBegin(ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const void* quick_code = m->GetEntryPointFromQuickCompiledCodePtrSize(
         InstructionSetPointerSize(oat_dumper_->GetOatInstructionSet()));
@@ -1631,7 +1672,7 @@
     return quick_code;
   }
 
-  uint32_t GetQuickOatCodeSize(mirror::ArtMethod* m)
+  uint32_t GetQuickOatCodeSize(ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetQuickOatCodeBegin(m));
     if (oat_code_begin == nullptr) {
@@ -1640,7 +1681,7 @@
     return oat_code_begin[-1];
   }
 
-  const void* GetQuickOatCodeEnd(mirror::ArtMethod* m)
+  const void* GetQuickOatCodeEnd(ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetQuickOatCodeBegin(m));
     if (oat_code_begin == nullptr) {
@@ -1649,8 +1690,7 @@
     return oat_code_begin + GetQuickOatCodeSize(m);
   }
 
-  static void Callback(mirror::Object* obj, void* arg)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  static void Callback(mirror::Object* obj, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(obj != nullptr);
     DCHECK(arg != nullptr);
     ImageDumper* state = reinterpret_cast<ImageDumper*>(arg);
@@ -1672,9 +1712,6 @@
       mirror::Class* klass = obj->AsClass();
       os << StringPrintf("%p: java.lang.Class \"%s\" (", obj, PrettyDescriptor(klass).c_str())
          << klass->GetStatus() << ")\n";
-    } else if (obj->IsArtMethod()) {
-      os << StringPrintf("%p: java.lang.reflect.ArtMethod %s\n", obj,
-                         PrettyMethod(obj->AsArtMethod()).c_str());
     } else if (obj_class->IsStringClass()) {
       os << StringPrintf("%p: java.lang.String %s\n", obj,
                          PrintableString(obj->AsString()->ToModifiedUtf8().c_str()).c_str());
@@ -1684,10 +1721,11 @@
     Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
     std::ostream indent_os(&indent_filter);
     DumpFields(indent_os, obj, obj_class);
+    const auto image_pointer_size =
+        InstructionSetPointerSize(state->oat_dumper_->GetOatInstructionSet());
     if (obj->IsObjectArray()) {
-      mirror::ObjectArray<mirror::Object>* obj_array = obj->AsObjectArray<mirror::Object>();
-      int32_t length = obj_array->GetLength();
-      for (int32_t i = 0; i < length; i++) {
+      auto* obj_array = obj->AsObjectArray<mirror::Object>();
+      for (int32_t i = 0, length = obj_array->GetLength(); i < length; i++) {
         mirror::Object* value = obj_array->Get(i);
         size_t run = 0;
         for (int32_t j = i + 1; j < length; j++) {
@@ -1719,87 +1757,119 @@
           PrintField(indent2_os, &sfields[i], sfields[i].GetDeclaringClass());
         }
       }
-    } else if (obj->IsArtMethod()) {
-      const size_t image_pointer_size = InstructionSetPointerSize(
-          state->oat_dumper_->GetOatInstructionSet());
-      mirror::ArtMethod* method = obj->AsArtMethod();
-      if (method->IsNative()) {
-        DCHECK(method->GetNativeGcMap(image_pointer_size) == nullptr) << PrettyMethod(method);
-        DCHECK(method->GetMappingTable(image_pointer_size) == nullptr) << PrettyMethod(method);
-        bool first_occurrence;
-        const void* quick_oat_code = state->GetQuickOatCodeBegin(method);
-        uint32_t quick_oat_code_size = state->GetQuickOatCodeSize(method);
-        state->ComputeOatSize(quick_oat_code, &first_occurrence);
-        if (first_occurrence) {
-          state->stats_.native_to_managed_code_bytes += quick_oat_code_size;
-        }
-        if (quick_oat_code != method->GetEntryPointFromQuickCompiledCodePtrSize(
-            image_pointer_size)) {
-          indent_os << StringPrintf("OAT CODE: %p\n", quick_oat_code);
-        }
-      } else if (method->IsAbstract() || method->IsCalleeSaveMethod() ||
-          method->IsResolutionMethod() || method->IsImtConflictMethod() ||
-          method->IsImtUnimplementedMethod() || method->IsClassInitializer()) {
-        DCHECK(method->GetNativeGcMap(image_pointer_size) == nullptr) << PrettyMethod(method);
-        DCHECK(method->GetMappingTable(image_pointer_size) == nullptr) << PrettyMethod(method);
-      } else {
-        const DexFile::CodeItem* code_item = method->GetCodeItem();
-        size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
-        state->stats_.dex_instruction_bytes += dex_instruction_bytes;
-
-        bool first_occurrence;
-        size_t gc_map_bytes =
-            state->ComputeOatSize(method->GetNativeGcMap(image_pointer_size), &first_occurrence);
-        if (first_occurrence) {
-          state->stats_.gc_map_bytes += gc_map_bytes;
-        }
-
-        size_t pc_mapping_table_bytes =
-            state->ComputeOatSize(method->GetMappingTable(image_pointer_size), &first_occurrence);
-        if (first_occurrence) {
-          state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
-        }
-
-        size_t vmap_table_bytes =
-            state->ComputeOatSize(method->GetVmapTable(image_pointer_size), &first_occurrence);
-        if (first_occurrence) {
-          state->stats_.vmap_table_bytes += vmap_table_bytes;
-        }
-
-        const void* quick_oat_code_begin = state->GetQuickOatCodeBegin(method);
-        const void* quick_oat_code_end = state->GetQuickOatCodeEnd(method);
-        uint32_t quick_oat_code_size = state->GetQuickOatCodeSize(method);
-        state->ComputeOatSize(quick_oat_code_begin, &first_occurrence);
-        if (first_occurrence) {
-          state->stats_.managed_code_bytes += quick_oat_code_size;
-          if (method->IsConstructor()) {
-            if (method->IsStatic()) {
-              state->stats_.class_initializer_code_bytes += quick_oat_code_size;
-            } else if (dex_instruction_bytes > kLargeConstructorDexBytes) {
-              state->stats_.large_initializer_code_bytes += quick_oat_code_size;
-            }
-          } else if (dex_instruction_bytes > kLargeMethodDexBytes) {
-            state->stats_.large_method_code_bytes += quick_oat_code_size;
+    } else {
+      auto it = state->dex_cache_arrays_.find(obj);
+      if (it != state->dex_cache_arrays_.end()) {
+        const auto& field_section = state->image_header_.GetImageSection(
+            ImageHeader::kSectionArtFields);
+        const auto& method_section = state->image_header_.GetMethodsSection();
+        auto* arr = down_cast<mirror::PointerArray*>(obj);
+        for (int32_t i = 0, length = arr->GetLength(); i < length; i++) {
+          void* elem = arr->GetElementPtrSize<void*>(i, image_pointer_size);
+          size_t run = 0;
+          for (int32_t j = i + 1; j < length &&
+              elem == arr->GetElementPtrSize<void*>(j, image_pointer_size); j++, run++) { }
+          if (run == 0) {
+            indent_os << StringPrintf("%d: ", i);
+          } else {
+            indent_os << StringPrintf("%d to %zd: ", i, i + run);
+            i = i + run;
           }
+          auto offset = reinterpret_cast<uint8_t*>(elem) - state->image_space_.Begin();
+          std::string msg;
+          if (field_section.Contains(offset)) {
+            msg = PrettyField(reinterpret_cast<ArtField*>(elem));
+          } else if (method_section.Contains(offset)) {
+            msg = PrettyMethod(reinterpret_cast<ArtMethod*>(elem));
+          } else {
+            msg = "Unknown type";
+          }
+          indent_os << StringPrintf("%p   %s\n", elem, msg.c_str());
         }
-        state->stats_.managed_code_bytes_ignoring_deduplication += quick_oat_code_size;
-
-        indent_os << StringPrintf("OAT CODE: %p-%p\n", quick_oat_code_begin, quick_oat_code_end);
-        indent_os << StringPrintf("SIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n",
-                                  dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes);
-
-        size_t total_size = dex_instruction_bytes + gc_map_bytes + pc_mapping_table_bytes +
-            vmap_table_bytes + quick_oat_code_size + object_bytes;
-
-        double expansion =
-            static_cast<double>(quick_oat_code_size) / static_cast<double>(dex_instruction_bytes);
-        state->stats_.ComputeOutliers(total_size, expansion, method);
       }
     }
     std::string temp;
     state->stats_.Update(obj_class->GetDescriptor(&temp), object_bytes);
   }
 
+  void DumpMethod(ArtMethod* method, ImageDumper* state, std::ostream& indent_os)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    DCHECK(method != nullptr);
+    const auto image_pointer_size =
+        InstructionSetPointerSize(state->oat_dumper_->GetOatInstructionSet());
+    if (method->IsNative()) {
+      DCHECK(method->GetNativeGcMap(image_pointer_size) == nullptr) << PrettyMethod(method);
+      DCHECK(method->GetMappingTable(image_pointer_size) == nullptr) << PrettyMethod(method);
+      bool first_occurrence;
+      const void* quick_oat_code = state->GetQuickOatCodeBegin(method);
+      uint32_t quick_oat_code_size = state->GetQuickOatCodeSize(method);
+      state->ComputeOatSize(quick_oat_code, &first_occurrence);
+      if (first_occurrence) {
+        state->stats_.native_to_managed_code_bytes += quick_oat_code_size;
+      }
+      if (quick_oat_code != method->GetEntryPointFromQuickCompiledCodePtrSize(image_pointer_size)) {
+        indent_os << StringPrintf("OAT CODE: %p\n", quick_oat_code);
+      }
+    } else if (method->IsAbstract() || method->IsCalleeSaveMethod() ||
+      method->IsResolutionMethod() || method->IsImtConflictMethod() ||
+      method->IsImtUnimplementedMethod() || method->IsClassInitializer()) {
+      DCHECK(method->GetNativeGcMap(image_pointer_size) == nullptr) << PrettyMethod(method);
+      DCHECK(method->GetMappingTable(image_pointer_size) == nullptr) << PrettyMethod(method);
+    } else {
+      const DexFile::CodeItem* code_item = method->GetCodeItem();
+      size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
+      state->stats_.dex_instruction_bytes += dex_instruction_bytes;
+
+      bool first_occurrence;
+      size_t gc_map_bytes = state->ComputeOatSize(
+          method->GetNativeGcMap(image_pointer_size), &first_occurrence);
+      if (first_occurrence) {
+        state->stats_.gc_map_bytes += gc_map_bytes;
+      }
+
+      size_t pc_mapping_table_bytes = state->ComputeOatSize(
+          method->GetMappingTable(image_pointer_size), &first_occurrence);
+      if (first_occurrence) {
+        state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
+      }
+
+      size_t vmap_table_bytes = state->ComputeOatSize(
+          method->GetVmapTable(image_pointer_size), &first_occurrence);
+      if (first_occurrence) {
+        state->stats_.vmap_table_bytes += vmap_table_bytes;
+      }
+
+      const void* quick_oat_code_begin = state->GetQuickOatCodeBegin(method);
+      const void* quick_oat_code_end = state->GetQuickOatCodeEnd(method);
+      uint32_t quick_oat_code_size = state->GetQuickOatCodeSize(method);
+      state->ComputeOatSize(quick_oat_code_begin, &first_occurrence);
+      if (first_occurrence) {
+        state->stats_.managed_code_bytes += quick_oat_code_size;
+        if (method->IsConstructor()) {
+          if (method->IsStatic()) {
+            state->stats_.class_initializer_code_bytes += quick_oat_code_size;
+          } else if (dex_instruction_bytes > kLargeConstructorDexBytes) {
+            state->stats_.large_initializer_code_bytes += quick_oat_code_size;
+          }
+        } else if (dex_instruction_bytes > kLargeMethodDexBytes) {
+          state->stats_.large_method_code_bytes += quick_oat_code_size;
+        }
+      }
+      state->stats_.managed_code_bytes_ignoring_deduplication += quick_oat_code_size;
+
+      indent_os << StringPrintf("OAT CODE: %p-%p\n", quick_oat_code_begin, quick_oat_code_end);
+      indent_os << StringPrintf("SIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n",
+      dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes);
+
+      size_t total_size = dex_instruction_bytes + gc_map_bytes + pc_mapping_table_bytes +
+          vmap_table_bytes + quick_oat_code_size + ArtMethod::ObjectSize(image_pointer_size);
+
+      double expansion =
+      static_cast<double>(quick_oat_code_size) / static_cast<double>(dex_instruction_bytes);
+      state->stats_.ComputeOutliers(total_size, expansion, method);
+    }
+  }
+
   std::set<const void*> already_seen_;
   // Compute the size of the given data within the oat file and whether this is the first time
   // this data has been requested
@@ -1820,6 +1890,8 @@
 
     size_t header_bytes;
     size_t object_bytes;
+    size_t art_field_bytes;
+    size_t art_method_bytes;
     size_t bitmap_bytes;
     size_t alignment_bytes;
 
@@ -1837,7 +1909,7 @@
 
     size_t dex_instruction_bytes;
 
-    std::vector<mirror::ArtMethod*> method_outlier;
+    std::vector<ArtMethod*> method_outlier;
     std::vector<size_t> method_outlier_size;
     std::vector<double> method_outlier_expansion;
     std::vector<std::pair<std::string, size_t>> oat_dex_file_sizes;
@@ -1847,6 +1919,8 @@
           file_bytes(0),
           header_bytes(0),
           object_bytes(0),
+          art_field_bytes(0),
+          art_method_bytes(0),
           bitmap_bytes(0),
           alignment_bytes(0),
           managed_code_bytes(0),
@@ -1891,7 +1965,7 @@
       return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
     }
 
-    void ComputeOutliers(size_t total_size, double expansion, mirror::ArtMethod* method) {
+    void ComputeOutliers(size_t total_size, double expansion, ArtMethod* method) {
       method_outlier_size.push_back(total_size);
       method_outlier_expansion.push_back(expansion);
       method_outlier.push_back(method);
@@ -2004,16 +2078,21 @@
            << "art_file_bytes = header_bytes + object_bytes + alignment_bytes\n";
         Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
         std::ostream indent_os(&indent_filter);
-        indent_os << StringPrintf("header_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "object_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "bitmap_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
-                                  "alignment_bytes =  %8zd (%2.0f%% of art file bytes)\n\n",
+        indent_os << StringPrintf("header_bytes     =  %8zd (%2.0f%% of art file bytes)\n"
+                                  "object_bytes     =  %8zd (%2.0f%% of art file bytes)\n"
+                                  "art_field_bytes  =  %8zd (%2.0f%% of art file bytes)\n"
+                                  "art_method_bytes =  %8zd (%2.0f%% of art file bytes)\n"
+                                  "bitmap_bytes     =  %8zd (%2.0f%% of art file bytes)\n"
+                                  "alignment_bytes  =  %8zd (%2.0f%% of art file bytes)\n\n",
                                   header_bytes, PercentOfFileBytes(header_bytes),
                                   object_bytes, PercentOfFileBytes(object_bytes),
+                                  art_field_bytes, PercentOfFileBytes(art_field_bytes),
+                                  art_method_bytes, PercentOfFileBytes(art_method_bytes),
                                   bitmap_bytes, PercentOfFileBytes(bitmap_bytes),
                                   alignment_bytes, PercentOfFileBytes(alignment_bytes))
             << std::flush;
-        CHECK_EQ(file_bytes, bitmap_bytes + header_bytes + object_bytes + alignment_bytes);
+        CHECK_EQ(file_bytes, header_bytes + object_bytes + art_field_bytes + art_method_bytes +
+            bitmap_bytes + alignment_bytes);
       }
 
       os << "object_bytes breakdown:\n";
@@ -2093,6 +2172,7 @@
   const ImageHeader& image_header_;
   std::unique_ptr<OatDumper> oat_dumper_;
   OatDumperOptions* oat_dumper_options_;
+  std::set<mirror::Object*> dex_cache_arrays_;
 
   DISALLOW_COPY_AND_ASSIGN(ImageDumper);
 };
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 8db1d23..007125c 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -25,6 +25,7 @@
 #include <vector>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/dumpable.h"
 #include "base/scoped_flock.h"
 #include "base/stringpiece.h"
@@ -35,8 +36,9 @@
 #include "elf_file_impl.h"
 #include "gc/space/image_space.h"
 #include "image.h"
-#include "mirror/art_method-inl.h"
+#include "mirror/abstract_method.h"
 #include "mirror/object-inl.h"
+#include "mirror/method.h"
 #include "mirror/reference.h"
 #include "noop_compiler_callbacks.h"
 #include "offsets.h"
@@ -120,7 +122,7 @@
   }
   ImageHeader image_header;
   if (sizeof(image_header) != input_image->Read(reinterpret_cast<char*>(&image_header),
-                                              sizeof(image_header), 0)) {
+                                                sizeof(image_header), 0)) {
     LOG(ERROR) << "Unable to read image header from image file " << input_image->GetPath();
     return false;
   }
@@ -416,12 +418,22 @@
 }
 
 void PatchOat::PatchArtFields(const ImageHeader* image_header) {
-  const size_t art_field_size = image_header->GetArtFieldsSize();
-  const size_t art_field_offset = image_header->GetArtFieldsOffset();
-  for (size_t pos = 0; pos < art_field_size; pos += sizeof(ArtField)) {
-    auto* field = reinterpret_cast<ArtField*>(heap_->Begin() + art_field_offset + pos);
-    auto* dest_field = RelocatedCopyOf(field);
-    dest_field->SetDeclaringClass(RelocatedAddressOfPointer(field->GetDeclaringClass()));
+  const auto& section = image_header->GetImageSection(ImageHeader::kSectionArtFields);
+  for (size_t pos = 0; pos < section.Size(); pos += sizeof(ArtField)) {
+    auto* src = reinterpret_cast<ArtField*>(heap_->Begin() + section.Offset() + pos);
+    auto* dest = RelocatedCopyOf(src);
+    dest->SetDeclaringClass(RelocatedAddressOfPointer(src->GetDeclaringClass()));
+  }
+}
+
+void PatchOat::PatchArtMethods(const ImageHeader* image_header) {
+  const auto& section = image_header->GetMethodsSection();
+  const size_t pointer_size = InstructionSetPointerSize(isa_);
+  size_t method_size = ArtMethod::ObjectSize(pointer_size);
+  for (size_t pos = 0; pos < section.Size(); pos += method_size) {
+    auto* src = reinterpret_cast<ArtMethod*>(heap_->Begin() + section.Offset() + pos);
+    auto* dest = RelocatedCopyOf(src);
+    FixupMethod(src, dest);
   }
 }
 
@@ -431,31 +443,35 @@
   for (size_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
     auto* dex_cache = dex_caches->GetWithoutChecks(i);
     auto* fields = dex_cache->GetResolvedFields();
-    if (fields == nullptr) {
-      continue;
+    if (fields != nullptr) {
+      CHECK(!fields->IsObjectArray());
+      CHECK(fields->IsArrayInstance());
+      FixupNativePointerArray(fields);
     }
-    CHECK(!fields->IsObjectArray());
-    CHECK(fields->IsArrayInstance());
-    auto* component_type = fields->GetClass()->GetComponentType();
-    if (component_type->IsPrimitiveInt()) {
-      mirror::IntArray* arr = fields->AsIntArray();
-      mirror::IntArray* copy_arr = down_cast<mirror::IntArray*>(RelocatedCopyOf(arr));
-      for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) {
-        auto f = arr->GetWithoutChecks(j);
-        if (f != 0) {
-          copy_arr->SetWithoutChecks<false>(j, f + delta_);
-        }
-      }
-    } else {
-      CHECK(component_type->IsPrimitiveLong());
-      mirror::LongArray* arr = fields->AsLongArray();
-      mirror::LongArray* copy_arr = down_cast<mirror::LongArray*>(RelocatedCopyOf(arr));
-      for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) {
-        auto f = arr->GetWithoutChecks(j);
-        if (f != 0) {
-          copy_arr->SetWithoutChecks<false>(j, f + delta_);
-        }
-      }
+    auto* methods = dex_cache->GetResolvedMethods();
+    if (methods != nullptr) {
+      CHECK(!methods->IsObjectArray());
+      CHECK(methods->IsArrayInstance());
+      FixupNativePointerArray(methods);
+    }
+  }
+}
+
+void PatchOat::FixupNativePointerArray(mirror::PointerArray* object) {
+  if (object->IsIntArray()) {
+    mirror::IntArray* arr = object->AsIntArray();
+    mirror::IntArray* copy_arr = down_cast<mirror::IntArray*>(RelocatedCopyOf(arr));
+    for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) {
+      copy_arr->SetWithoutChecks<false>(
+          j, RelocatedAddressOfIntPointer(arr->GetWithoutChecks(j)));
+    }
+  } else {
+    CHECK(object->IsLongArray());
+    mirror::LongArray* arr = object->AsLongArray();
+    mirror::LongArray* copy_arr = down_cast<mirror::LongArray*>(RelocatedCopyOf(arr));
+    for (size_t j = 0, count2 = arr->GetLength(); j < count2; ++j) {
+      copy_arr->SetWithoutChecks<false>(
+          j, RelocatedAddressOfIntPointer(arr->GetWithoutChecks(j)));
     }
   }
 }
@@ -470,6 +486,9 @@
   // Patch and update ArtFields.
   PatchArtFields(image_header);
 
+  // Patch and update ArtMethods.
+  PatchArtMethods(image_header);
+
   // Patch dex file int/long arrays which point to ArtFields.
   PatchDexFileArrays(img_roots);
 
@@ -545,40 +564,63 @@
   }
   PatchOat::PatchVisitor visitor(this, copy);
   object->VisitReferences<true, kVerifyNone>(visitor, visitor);
-  if (object->IsArtMethod<kVerifyNone>()) {
-    FixupMethod(down_cast<mirror::ArtMethod*>(object), down_cast<mirror::ArtMethod*>(copy));
-  } else if (object->IsClass<kVerifyNone>()) {
-    mirror::Class* klass = down_cast<mirror::Class*>(object);
-    down_cast<mirror::Class*>(copy)->SetSFieldsUnchecked(
-        RelocatedAddressOfPointer(klass->GetSFields()));
-    down_cast<mirror::Class*>(copy)->SetIFieldsUnchecked(
-        RelocatedAddressOfPointer(klass->GetIFields()));
+  if (object->IsClass<kVerifyNone>()) {
+    auto* klass = object->AsClass();
+    auto* copy_klass = down_cast<mirror::Class*>(copy);
+    copy_klass->SetSFieldsUnchecked(RelocatedAddressOfPointer(klass->GetSFields()));
+    copy_klass->SetIFieldsUnchecked(RelocatedAddressOfPointer(klass->GetIFields()));
+    copy_klass->SetDirectMethodsPtrUnchecked(
+        RelocatedAddressOfPointer(klass->GetDirectMethodsPtr()));
+    copy_klass->SetVirtualMethodsPtr(RelocatedAddressOfPointer(klass->GetVirtualMethodsPtr()));
+    auto* vtable = klass->GetVTable();
+    if (vtable != nullptr) {
+      FixupNativePointerArray(vtable);
+    }
+    auto* iftable = klass->GetIfTable();
+    if (iftable != nullptr) {
+      for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
+        if (iftable->GetMethodArrayCount(i) > 0) {
+          auto* method_array = iftable->GetMethodArray(i);
+          CHECK(method_array != nullptr);
+          FixupNativePointerArray(method_array);
+        }
+      }
+    }
+    if (klass->ShouldHaveEmbeddedImtAndVTable()) {
+      const size_t pointer_size = InstructionSetPointerSize(isa_);
+      for (int32_t i = 0; i < klass->GetEmbeddedVTableLength(); ++i) {
+        copy_klass->SetEmbeddedVTableEntryUnchecked(i, RelocatedAddressOfPointer(
+            klass->GetEmbeddedVTableEntry(i, pointer_size)), pointer_size);
+      }
+      for (size_t i = 0; i < mirror::Class::kImtSize; ++i) {
+        copy_klass->SetEmbeddedImTableEntry(i, RelocatedAddressOfPointer(
+            klass->GetEmbeddedImTableEntry(i, pointer_size)), pointer_size);
+      }
+    }
+  }
+  if (object->GetClass() == mirror::Method::StaticClass() ||
+      object->GetClass() == mirror::Constructor::StaticClass()) {
+    // Need to go update the ArtMethod.
+    auto* dest = down_cast<mirror::AbstractMethod*>(copy);
+    auto* src = down_cast<mirror::AbstractMethod*>(object);
+    dest->SetArtMethod(RelocatedAddressOfPointer(src->GetArtMethod()));
   }
 }
 
-void PatchOat::FixupMethod(mirror::ArtMethod* object, mirror::ArtMethod* copy) {
+void PatchOat::FixupMethod(ArtMethod* object, ArtMethod* copy) {
   const size_t pointer_size = InstructionSetPointerSize(isa_);
+  copy->CopyFrom(object, pointer_size);
   // Just update the entry points if it looks like we should.
   // TODO: sanity check all the pointers' values
-  uintptr_t quick= reinterpret_cast<uintptr_t>(
-      object->GetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(pointer_size));
-  if (quick != 0) {
-    copy->SetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(
-        reinterpret_cast<void*>(quick + delta_), pointer_size);
-  }
-  uintptr_t interpreter = reinterpret_cast<uintptr_t>(
-      object->GetEntryPointFromInterpreterPtrSize<kVerifyNone>(pointer_size));
-  if (interpreter != 0) {
-    copy->SetEntryPointFromInterpreterPtrSize<kVerifyNone>(
-        reinterpret_cast<mirror::EntryPointFromInterpreter*>(interpreter + delta_), pointer_size);
-  }
-
-  uintptr_t native_method = reinterpret_cast<uintptr_t>(
-      object->GetEntryPointFromJniPtrSize(pointer_size));
-  if (native_method != 0) {
-    copy->SetEntryPointFromJniPtrSize<kVerifyNone>(
-        reinterpret_cast<void*>(native_method + delta_), pointer_size);
-  }
+  copy->SetDeclaringClass(RelocatedAddressOfPointer(object->GetDeclaringClass()));
+  copy->SetDexCacheResolvedMethods(RelocatedAddressOfPointer(object->GetDexCacheResolvedMethods()));
+  copy->SetDexCacheResolvedTypes(RelocatedAddressOfPointer(object->GetDexCacheResolvedTypes()));
+  copy->SetEntryPointFromQuickCompiledCodePtrSize(RelocatedAddressOfPointer(
+      object->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)), pointer_size);
+  copy->SetEntryPointFromInterpreterPtrSize(RelocatedAddressOfPointer(
+      object->GetEntryPointFromInterpreterPtrSize(pointer_size)), pointer_size);
+  copy->SetEntryPointFromJniPtrSize(RelocatedAddressOfPointer(
+      object->GetEntryPointFromJniPtrSize(pointer_size)), pointer_size);
 }
 
 bool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogger* timings,
diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h
index 8f16f6b..7b9c8bd 100644
--- a/patchoat/patchoat.h
+++ b/patchoat/patchoat.h
@@ -28,14 +28,15 @@
 
 namespace art {
 
+class ArtMethod;
 class ImageHeader;
 class OatHeader;
 
 namespace mirror {
 class Object;
+class PointerArray;
 class Reference;
 class Class;
-class ArtMethod;
 }  // namespace mirror
 
 class PatchOat {
@@ -99,7 +100,9 @@
 
   void VisitObject(mirror::Object* obj)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void FixupMethod(mirror::ArtMethod* object, mirror::ArtMethod* copy)
+  void FixupMethod(ArtMethod* object, ArtMethod* copy)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void FixupNativePointerArray(mirror::PointerArray* object)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool InHeap(mirror::Object*);
 
@@ -112,6 +115,7 @@
 
   bool PatchImage() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void PatchArtFields(const ImageHeader* image_header) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void PatchArtMethods(const ImageHeader* image_header) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void PatchDexFileArrays(mirror::ObjectArray<mirror::Object>* img_roots)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -133,8 +137,28 @@
 
   template <typename T>
   T* RelocatedAddressOfPointer(T* obj) {
-    return obj == nullptr ? nullptr :
-        reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(obj) + delta_);
+    if (obj == nullptr) {
+      return obj;
+    }
+    auto ret = reinterpret_cast<uintptr_t>(obj) + delta_;
+    // Trim off high bits in case negative relocation with 64 bit patchoat.
+    if (InstructionSetPointerSize(isa_) == sizeof(uint32_t)) {
+      ret = static_cast<uintptr_t>(static_cast<uint32_t>(ret));
+    }
+    return reinterpret_cast<T*>(ret);
+  }
+
+  template <typename T>
+  T RelocatedAddressOfIntPointer(T obj) {
+    if (obj == 0) {
+      return obj;
+    }
+    T ret = obj + delta_;
+    // Trim off high bits in case negative relocation with 64 bit patchoat.
+    if (InstructionSetPointerSize(isa_) == 4) {
+      ret = static_cast<T>(static_cast<uint32_t>(ret));
+    }
+    return ret;
   }
 
   // Look up the oat header from any elf file.
diff --git a/runtime/Android.mk b/runtime/Android.mk
index a4fa24d..b38f9bc 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -20,6 +20,7 @@
 
 LIBART_COMMON_SRC_FILES := \
   art_field.cc \
+  art_method.cc \
   atomic.cc.arm \
   barrier.cc \
   base/allocator.cc \
@@ -102,7 +103,6 @@
   mem_map.cc \
   memory_region.cc \
   mirror/abstract_method.cc \
-  mirror/art_method.cc \
   mirror/array.cc \
   mirror/class.cc \
   mirror/dex_cache.cc \
@@ -317,6 +317,7 @@
   gc/space/region_space.h \
   gc/space/space.h \
   gc/heap.h \
+  image.h \
   instrumentation.h \
   indirect_reference_table.h \
   invoke_type.h \
diff --git a/runtime/arch/arch_test.cc b/runtime/arch/arch_test.cc
index 5733ab6..40e2cd3 100644
--- a/runtime/arch/arch_test.cc
+++ b/runtime/arch/arch_test.cc
@@ -16,8 +16,8 @@
 
 #include <stdint.h>
 
+#include "art_method-inl.h"
 #include "common_runtime_test.h"
-#include "mirror/art_method-inl.h"
 #include "quick/quick_method_frame_info.h"
 
 namespace art {
@@ -38,7 +38,7 @@
     t->TransitionFromSuspendedToRunnable();  // So we can create callee-save methods.
 
     r->SetInstructionSet(isa);
-    mirror::ArtMethod* save_method = r->CreateCalleeSaveMethod();
+    ArtMethod* save_method = r->CreateCalleeSaveMethod();
     r->SetCalleeSaveMethod(save_method, type);
     QuickMethodFrameInfo frame_info = save_method->GetQuickFrameInfo();
     EXPECT_EQ(frame_info.FrameSizeInBytes(), save_size) << "Expected and real size differs for "
diff --git a/runtime/arch/arm/context_arm.cc b/runtime/arch/arm/context_arm.cc
index c0e658c..403d348 100644
--- a/runtime/arch/arm/context_arm.cc
+++ b/runtime/arch/arm/context_arm.cc
@@ -16,8 +16,8 @@
 
 #include "context_arm.h"
 
+#include "art_method-inl.h"
 #include "base/bit_utils.h"
-#include "mirror/art_method-inl.h"
 #include "quick/quick_method_frame_info.h"
 
 namespace art {
@@ -36,7 +36,7 @@
 }
 
 void ArmContext::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
   int spill_pos = 0;
 
diff --git a/runtime/arch/arm/fault_handler_arm.cc b/runtime/arch/arm/fault_handler_arm.cc
index d84cb53..90b0d53 100644
--- a/runtime/arch/arm/fault_handler_arm.cc
+++ b/runtime/arch/arm/fault_handler_arm.cc
@@ -18,13 +18,13 @@
 #include "fault_handler.h"
 
 #include <sys/ucontext.h>
+
+#include "art_method-inl.h"
 #include "base/macros.h"
 #include "base/hex_dump.h"
 #include "globals.h"
 #include "base/logging.h"
 #include "base/hex_dump.h"
-#include "mirror/art_method.h"
-#include "mirror/art_method-inl.h"
 #include "thread.h"
 #include "thread-inl.h"
 
@@ -65,7 +65,7 @@
 }
 
 void FaultManager::GetMethodAndReturnPcAndSp(siginfo_t* siginfo ATTRIBUTE_UNUSED, void* context,
-                                             mirror::ArtMethod** out_method,
+                                             ArtMethod** out_method,
                                              uintptr_t* out_return_pc, uintptr_t* out_sp) {
   struct ucontext* uc = reinterpret_cast<struct ucontext*>(context);
   struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
@@ -81,10 +81,10 @@
   uintptr_t* overflow_addr = reinterpret_cast<uintptr_t*>(
       reinterpret_cast<uint8_t*>(*out_sp) - GetStackOverflowReservedBytes(kArm));
   if (overflow_addr == fault_addr) {
-    *out_method = reinterpret_cast<mirror::ArtMethod*>(sc->arm_r0);
+    *out_method = reinterpret_cast<ArtMethod*>(sc->arm_r0);
   } else {
     // The method is at the top of the stack.
-    *out_method = reinterpret_cast<mirror::ArtMethod*>(reinterpret_cast<uintptr_t*>(*out_sp)[0]);
+    *out_method = reinterpret_cast<ArtMethod*>(reinterpret_cast<uintptr_t*>(*out_sp)[0]);
   }
 
   // Work out the return PC.  This will be the address of the instruction
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 6e53ba4..064f5a6 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -419,7 +419,7 @@
     mov    r4, #SUSPEND_CHECK_INTERVAL     @ reset r4 to suspend check interval
 #endif
 
-    ldr    ip, [r0, #MIRROR_ART_METHOD_QUICK_CODE_OFFSET_32]  @ get pointer to the code
+    ldr    ip, [r0, #ART_METHOD_QUICK_CODE_OFFSET_32]  @ get pointer to the code
     blx    ip                              @ call the method
 
     mov    sp, r11                         @ restore the stack pointer
diff --git a/runtime/arch/arm/quick_entrypoints_cc_arm.cc b/runtime/arch/arm/quick_entrypoints_cc_arm.cc
index a3acd7e..ce531f0 100644
--- a/runtime/arch/arm/quick_entrypoints_cc_arm.cc
+++ b/runtime/arch/arm/quick_entrypoints_cc_arm.cc
@@ -14,23 +14,23 @@
  * limitations under the License.
  */
 
-#include "mirror/art_method.h"
+#include "art_method.h"
 #include "utils.h"  // For RoundUp().
 
 namespace art {
 
 // Assembly stub that does the final part of the up-call into Java.
-extern "C" void art_quick_invoke_stub_internal(mirror::ArtMethod*, uint32_t*, uint32_t,
+extern "C" void art_quick_invoke_stub_internal(ArtMethod*, uint32_t*, uint32_t,
                                                Thread* self, JValue* result, uint32_t, uint32_t*,
                                                uint32_t*);
 
 template <bool kIsStatic>
-static void quick_invoke_reg_setup(mirror::ArtMethod* method, uint32_t* args, uint32_t args_size,
+static void quick_invoke_reg_setup(ArtMethod* method, uint32_t* args, uint32_t args_size,
                                    Thread* self, JValue* result, const char* shorty) {
   // Note: We do not follow aapcs ABI in quick code for both softfp and hardfp.
   uint32_t core_reg_args[4];  // r0 ~ r3
   uint32_t fp_reg_args[16];  // s0 ~ s15 (d0 ~ d7)
-  uint32_t gpr_index = 1;  // Index into core registers. Reserve r0 for mirror::ArtMethod*.
+  uint32_t gpr_index = 1;  // Index into core registers. Reserve r0 for ArtMethod*.
   uint32_t fpr_index = 0;  // Index into float registers.
   uint32_t fpr_double_index = 0;  // Index into float registers for doubles.
   uint32_t arg_index = 0;  // Index into argument array.
@@ -99,16 +99,16 @@
       core_reg_args, fp_reg_args);
 }
 
-// Called by art::mirror::ArtMethod::Invoke to do entry into a non-static method.
+// Called by art::ArtMethod::Invoke to do entry into a non-static method.
 // TODO: migrate into an assembly implementation as with ARM64.
-extern "C" void art_quick_invoke_stub(mirror::ArtMethod* method, uint32_t* args, uint32_t args_size,
+extern "C" void art_quick_invoke_stub(ArtMethod* method, uint32_t* args, uint32_t args_size,
                                       Thread* self, JValue* result, const char* shorty) {
   quick_invoke_reg_setup<false>(method, args, args_size, self, result, shorty);
 }
 
-// Called by art::mirror::ArtMethod::Invoke to do entry into a static method.
+// Called by art::ArtMethod::Invoke to do entry into a static method.
 // TODO: migrate into an assembly implementation as with ARM64.
-extern "C" void art_quick_invoke_static_stub(mirror::ArtMethod* method, uint32_t* args,
+extern "C" void art_quick_invoke_static_stub(ArtMethod* method, uint32_t* args,
                                              uint32_t args_size, Thread* self, JValue* result,
                                              const char* shorty) {
   quick_invoke_reg_setup<true>(method, args, args_size, self, result, shorty);
diff --git a/runtime/arch/arm64/context_arm64.cc b/runtime/arch/arm64/context_arm64.cc
index 5488f9d..60becc6 100644
--- a/runtime/arch/arm64/context_arm64.cc
+++ b/runtime/arch/arm64/context_arm64.cc
@@ -18,8 +18,8 @@
 
 #include "context_arm64.h"
 
+#include "art_method-inl.h"
 #include "base/bit_utils.h"
-#include "mirror/art_method-inl.h"
 #include "quick/quick_method_frame_info.h"
 
 namespace art {
@@ -38,7 +38,7 @@
 }
 
 void Arm64Context::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
   int spill_pos = 0;
 
diff --git a/runtime/arch/arm64/fault_handler_arm64.cc b/runtime/arch/arm64/fault_handler_arm64.cc
index 0448c76..3e9ad0d 100644
--- a/runtime/arch/arm64/fault_handler_arm64.cc
+++ b/runtime/arch/arm64/fault_handler_arm64.cc
@@ -16,14 +16,15 @@
 
 
 #include "fault_handler.h"
+
 #include <sys/ucontext.h>
+
+#include "art_method-inl.h"
 #include "base/macros.h"
 #include "globals.h"
 #include "base/logging.h"
 #include "base/hex_dump.h"
 #include "registers_arm64.h"
-#include "mirror/art_method.h"
-#include "mirror/art_method-inl.h"
 #include "thread.h"
 #include "thread-inl.h"
 
@@ -53,7 +54,7 @@
 }
 
 void FaultManager::GetMethodAndReturnPcAndSp(siginfo_t* siginfo ATTRIBUTE_UNUSED, void* context,
-                                             mirror::ArtMethod** out_method,
+                                             ArtMethod** out_method,
                                              uintptr_t* out_return_pc, uintptr_t* out_sp) {
   struct ucontext *uc = reinterpret_cast<struct ucontext *>(context);
   struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
@@ -69,10 +70,10 @@
   uintptr_t* overflow_addr = reinterpret_cast<uintptr_t*>(
       reinterpret_cast<uint8_t*>(*out_sp) - GetStackOverflowReservedBytes(kArm64));
   if (overflow_addr == fault_addr) {
-    *out_method = reinterpret_cast<mirror::ArtMethod*>(sc->regs[0]);
+    *out_method = reinterpret_cast<ArtMethod*>(sc->regs[0]);
   } else {
     // The method is at the top of the stack.
-    *out_method = (reinterpret_cast<StackReference<mirror::ArtMethod>* >(*out_sp)[0]).AsMirrorPtr();
+    *out_method = *reinterpret_cast<ArtMethod**>(*out_sp);
   }
 
   // Work out the return PC.  This will be the address of the instruction
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index 7eb6c16..790158e 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -34,7 +34,7 @@
     THIS_LOAD_REQUIRES_READ_BARRIER
 
     // Loads appropriate callee-save-method.
-    ldr wIP0, [xIP0, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET ]
+    ldr xIP0, [xIP0, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET ]
 
     sub sp, sp, #176
     .cfi_adjust_cfa_offset 176
@@ -98,7 +98,7 @@
     THIS_LOAD_REQUIRES_READ_BARRIER
 
     // Loads appropriate callee-save-method.
-    ldr wIP0, [xIP0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET ]
+    ldr xIP0, [xIP0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET ]
 
     sub sp, sp, #96
     .cfi_adjust_cfa_offset 96
@@ -252,7 +252,7 @@
 
     // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
     THIS_LOAD_REQUIRES_READ_BARRIER
-    ldr wIP0, [xIP0, RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET ]
+    ldr xIP0, [xIP0, RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET ]
 
     SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
 
@@ -481,14 +481,14 @@
 .macro INVOKE_STUB_CREATE_FRAME
 
 SAVE_SIZE=15*8   // x4, x5, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, SP, LR, FP saved.
-SAVE_SIZE_AND_METHOD=SAVE_SIZE+STACK_REFERENCE_SIZE
+SAVE_SIZE_AND_METHOD=SAVE_SIZE+8
 
 
     mov x9, sp                             // Save stack pointer.
     .cfi_register sp,x9
 
     add x10, x2, # SAVE_SIZE_AND_METHOD    // calculate size of frame.
-    sub x10, sp, x10                       // Calculate SP position - saves + ArtMethod* +  args
+    sub x10, sp, x10                       // Calculate SP position - saves + ArtMethod* + args
     and x10, x10, # ~0xf                   // Enforce 16 byte stack alignment.
     mov sp, x10                            // Set new SP.
 
@@ -538,7 +538,7 @@
     // W2 - args length
     // X9 - destination address.
     // W10 - temporary
-    add x9, sp, #4                         // Destination address is bottom of stack + null.
+    add x9, sp, #8                         // Destination address is bottom of stack + null.
 
     // Use \@ to differentiate between macro invocations.
 .LcopyParams\@:
@@ -552,18 +552,14 @@
 
 .LendCopyParams\@:
 
-    // Store null into StackReference<Method>* at bottom of frame.
-    str wzr, [sp]
-
-#if (STACK_REFERENCE_SIZE != 4)
-#error "STACK_REFERENCE_SIZE(ARM64) size not as expected."
-#endif
+    // Store null into ArtMethod* at bottom of frame.
+    str xzr, [sp]
 .endm
 
 .macro INVOKE_STUB_CALL_AND_RETURN
 
     // load method-> METHOD_QUICK_CODE_OFFSET
-    ldr x9, [x0 , #MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64]
+    ldr x9, [x0, #ART_METHOD_QUICK_CODE_OFFSET_64]
     // Branch to method.
     blr x9
 
@@ -654,7 +650,7 @@
  *  | uint32_t out[n-1]    |
  *  |    :      :          |        Outs
  *  | uint32_t out[0]      |
- *  | StackRef<ArtMethod>  | <- SP  value=null
+ *  | ArtMethod*           | <- SP  value=null
  *  +----------------------+
  *
  * Outgoing registers:
@@ -1273,7 +1269,7 @@
     .extern \entrypoint
 ENTRY \name
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
-    ldr    w1, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
+    ldr    x1, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
     mov    x2, xSELF                  // pass Thread::Current
     bl     \entrypoint                // (uint32_t type_idx, Method* method, Thread*, SP)
     RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
@@ -1285,7 +1281,7 @@
     .extern \entrypoint
 ENTRY \name
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
-    ldr    w2, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
+    ldr    x2, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
     mov    x3, xSELF                  // pass Thread::Current
     bl     \entrypoint
     RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
@@ -1297,7 +1293,7 @@
     .extern \entrypoint
 ENTRY \name
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
-    ldr    w3, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
+    ldr    x3, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
     mov    x4, xSELF                  // pass Thread::Current
     bl     \entrypoint
     RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
@@ -1360,7 +1356,7 @@
 ENTRY art_quick_set64_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  // save callee saves in case of GC
     mov    x3, x1                     // Store value
-    ldr    w1, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
+    ldr    x1, [sp, #FRAME_SIZE_REFS_ONLY_CALLEE_SAVE] // Load referrer
     mov    x2, x3                     // Put value param
     mov    x3, xSELF                  // pass Thread::Current
     bl     artSet64StaticFromCode
@@ -1437,7 +1433,7 @@
     bl artQuickResolutionTrampoline  // (called, receiver, Thread*, SP)
     cbz x0, 1f
     mov xIP0, x0            // Remember returned code pointer in xIP0.
-    ldr w0, [sp, #0]        // artQuickResolutionTrampoline puts called method in *SP.
+    ldr x0, [sp, #0]        // artQuickResolutionTrampoline puts called method in *SP.
     RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
     br xIP0
 1:
diff --git a/runtime/arch/mips/context_mips.cc b/runtime/arch/mips/context_mips.cc
index 24892e9..53f2b65 100644
--- a/runtime/arch/mips/context_mips.cc
+++ b/runtime/arch/mips/context_mips.cc
@@ -16,8 +16,8 @@
 
 #include "context_mips.h"
 
+#include "art_method-inl.h"
 #include "base/bit_utils.h"
-#include "mirror/art_method-inl.h"
 #include "quick/quick_method_frame_info.h"
 
 namespace art {
@@ -36,7 +36,7 @@
 }
 
 void MipsContext::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
   int spill_pos = 0;
 
diff --git a/runtime/arch/mips/fault_handler_mips.cc b/runtime/arch/mips/fault_handler_mips.cc
index c9949d4..abe495b 100644
--- a/runtime/arch/mips/fault_handler_mips.cc
+++ b/runtime/arch/mips/fault_handler_mips.cc
@@ -35,7 +35,7 @@
 
 void FaultManager::GetMethodAndReturnPcAndSp(siginfo_t* siginfo ATTRIBUTE_UNUSED,
                                              void* context ATTRIBUTE_UNUSED,
-                                             mirror::ArtMethod** out_method ATTRIBUTE_UNUSED,
+                                             ArtMethod** out_method ATTRIBUTE_UNUSED,
                                              uintptr_t* out_return_pc ATTRIBUTE_UNUSED,
                                              uintptr_t* out_sp ATTRIBUTE_UNUSED) {
 }
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index c00d6cb..9e1dab6 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -523,7 +523,7 @@
     lw    $a1, 4($sp)           # copy arg value for a1
     lw    $a2, 8($sp)           # copy arg value for a2
     lw    $a3, 12($sp)          # copy arg value for a3
-    lw    $t9, MIRROR_ART_METHOD_QUICK_CODE_OFFSET_32($a0)  # get pointer to the code
+    lw    $t9, ART_METHOD_QUICK_CODE_OFFSET_32($a0)  # get pointer to the code
     jalr  $t9                   # call the method
     sw    $zero, 0($sp)         # store null for method* at bottom of frame
     move  $sp, $fp              # restore the stack
diff --git a/runtime/arch/mips64/context_mips64.cc b/runtime/arch/mips64/context_mips64.cc
index 8ce6cf0..6637c37 100644
--- a/runtime/arch/mips64/context_mips64.cc
+++ b/runtime/arch/mips64/context_mips64.cc
@@ -16,8 +16,8 @@
 
 #include "context_mips64.h"
 
+#include "art_method-inl.h"
 #include "base/bit_utils.h"
-#include "mirror/art_method-inl.h"
 #include "quick/quick_method_frame_info.h"
 
 namespace art {
@@ -36,7 +36,7 @@
 }
 
 void Mips64Context::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
   int spill_pos = 0;
 
diff --git a/runtime/arch/mips64/fault_handler_mips64.cc b/runtime/arch/mips64/fault_handler_mips64.cc
index 7b5cd49..277c2b2 100644
--- a/runtime/arch/mips64/fault_handler_mips64.cc
+++ b/runtime/arch/mips64/fault_handler_mips64.cc
@@ -35,7 +35,7 @@
 
 void FaultManager::GetMethodAndReturnPcAndSp(siginfo_t* siginfo ATTRIBUTE_UNUSED,
                                              void* context ATTRIBUTE_UNUSED,
-                                             mirror::ArtMethod** out_method ATTRIBUTE_UNUSED,
+                                             ArtMethod** out_method ATTRIBUTE_UNUSED,
                                              uintptr_t* out_return_pc ATTRIBUTE_UNUSED,
                                              uintptr_t* out_sp ATTRIBUTE_UNUSED) {
 }
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index 031f85f..c62e035 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -90,8 +90,8 @@
     ld      $v0, %got(_ZN3art7Runtime9instance_E)($gp)
     ld      $v0, 0($v0)
     THIS_LOAD_REQUIRES_READ_BARRIER
-    lwu     $v0, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET($v0)
-    sw      $v0, 0($sp)                                # Place Method* at bottom of stack.
+    ld      $v0, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET($v0)
+    sd      $v0, 0($sp)                                # Place ArtMethod* at bottom of stack.
     sd      $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
 .endm
 
@@ -133,8 +133,8 @@
     ld      $v0, %got(_ZN3art7Runtime9instance_E)($gp)
     ld      $v0, 0($v0)
     THIS_LOAD_REQUIRES_READ_BARRIER
-    lwu     $v0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET($v0)
-    sw      $v0, 0($sp)                                # Place Method* at bottom of stack.
+    ld      $v0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET($v0)
+    sd      $v0, 0($sp)                                # Place Method* at bottom of stack.
     sd      $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
 .endm
 
@@ -256,14 +256,14 @@
     ld      $v0, %got(_ZN3art7Runtime9instance_E)($gp)
     ld      $v0, 0($v0)
     THIS_LOAD_REQUIRES_READ_BARRIER
-    lwu     $v0, RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET($v0)
-    sw      $v0, 0($sp)                                # Place Method* at bottom of stack.
+    ld      $v0, RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET($v0)
+    sd      $v0, 0($sp)                                # Place Method* at bottom of stack.
     sd      $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
 .endm
 
 .macro SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_WITH_METHOD_IN_A0
     SETUP_REFS_AND_ARGS_CALLEE_SAVE_FRAME_INTERNAL
-    sw      $a0, 0($sp)                                # Place Method* at bottom of stack.
+    sd      $a0, 0($sp)                                # Place Method* at bottom of stack.
     sd      $sp, THREAD_TOP_QUICK_FRAME_OFFSET(rSELF)  # Place sp in Thread::Current()->top_quick_frame.
 .endm
 
@@ -641,7 +641,7 @@
     move   $s1, $a3              # move managed thread pointer into s1 (rSELF)
     move   $s8, $sp              # save sp in s8 (fp)
 
-    daddiu $t3, $a2, 20          # add 4 for method* and 16 for stack alignment
+    daddiu $t3, $a2, 24          # add 8 for ArtMethod* and 16 for stack alignment
     dsrl   $t3, $t3, 4           # shift the frame size right 4
     dsll   $t3, $t3, 4           # shift the frame size left 4 to align to 16 bytes
     dsubu  $sp, $sp, $t3         # reserve stack space for argument array
@@ -670,9 +670,9 @@
 call_fn:
     # call method (a0 and a1 have been untouched)
     lwu    $a1, 0($a1)           # make a1 = this ptr
-    sw     $a1, 4($sp)           # copy this ptr (skip 4 bytes for method*)
-    sw     $zero, 0($sp)         # store null for method* at bottom of frame
-    ld     $t9, MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64($a0)  # get pointer to the code
+    sw     $a1, 8($sp)           # copy this ptr (skip 8 bytes for ArtMethod*)
+    sd     $zero, 0($sp)         # store null for ArtMethod* at bottom of frame
+    ld     $t9, ART_METHOD_QUICK_CODE_OFFSET_64($a0)  # get pointer to the code
     jalr   $t9                   # call the method
     nop
     move   $sp, $s8              # restore sp
@@ -744,7 +744,7 @@
     move   $s1, $a3              # move managed thread pointer into s1 (rSELF)
     move   $s8, $sp              # save sp in s8 (fp)
 
-    daddiu $t3, $a2, 20          # add 4 for method* and 16 for stack alignment
+    daddiu $t3, $a2, 24          # add 8 for ArtMethod* and 16 for stack alignment
     dsrl   $t3, $t3, 4           # shift the frame size right 4
     dsll   $t3, $t3, 4           # shift the frame size left 4 to align to 16 bytes
     dsubu  $sp, $sp, $t3         # reserve stack space for argument array
@@ -752,7 +752,7 @@
     daddiu $t0, $a5, 1           # t0 = shorty[1] (skip 1 for return type)
     move   $t1, $a1              # t1 = arg_array
     move   $t2, $a2              # t2 = number of argument bytes remain
-    daddiu $v0, $sp, 4           # v0 points to where to copy arg_array
+    daddiu $v0, $sp, 8           # v0 points to where to copy arg_array
     LOOP_OVER_SHORTY_LOADING_REG a1, f13, call_sfn
     LOOP_OVER_SHORTY_LOADING_REG a2, f14, call_sfn
     LOOP_OVER_SHORTY_LOADING_REG a3, f15, call_sfn
@@ -773,8 +773,8 @@
 
 call_sfn:
     # call method (a0 has been untouched)
-    sw     $zero, 0($sp)         # store null for method* at bottom of frame
-    ld     $t9, MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64($a0)  # get pointer to the code
+    sd     $zero, 0($sp)         # store null for ArtMethod* at bottom of frame
+    ld     $t9, ART_METHOD_QUICK_CODE_OFFSET_64($a0)  # get pointer to the code
     jalr   $t9                   # call the method
     nop
     move   $sp, $s8              # restore sp
@@ -821,7 +821,7 @@
     .extern artHandleFillArrayDataFromCode
 ENTRY art_quick_handle_fill_data
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME  # save callee saves in case exception allocation triggers GC
-    lwu     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld      $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal     artHandleFillArrayDataFromCode              # (payload offset, Array*, method, Thread*)
     move    $a3, rSELF                                  # pass Thread::Current
     RETURN_IF_ZERO
@@ -969,7 +969,7 @@
     .extern artGetBooleanStaticFromCode
 ENTRY art_quick_get_boolean_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGetBooleanStaticFromCode   # (uint32_t field_idx, const Method* referrer, Thread*)
     move   $a2, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -981,7 +981,7 @@
     .extern artGetByteStaticFromCode
 ENTRY art_quick_get_byte_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGetByteStaticFromCode      # (uint32_t field_idx, const Method* referrer, Thread*)
     move   $a2, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -993,7 +993,7 @@
     .extern artGetCharStaticFromCode
 ENTRY art_quick_get_char_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGetCharStaticFromCode      # (uint32_t field_idx, const Method* referrer, Thread*)
     move   $a2, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1005,7 +1005,7 @@
     .extern artGetShortStaticFromCode
 ENTRY art_quick_get_short_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGetShortStaticFromCode     # (uint32_t field_idx, const Method* referrer, Thread*)
     move   $a2, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1017,7 +1017,7 @@
     .extern artGet32StaticFromCode
 ENTRY art_quick_get32_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGet32StaticFromCode        # (uint32_t field_idx, const Method* referrer, Thread*)
     move   $a2, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1029,7 +1029,7 @@
     .extern artGet64StaticFromCode
 ENTRY art_quick_get64_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGet64StaticFromCode        # (uint32_t field_idx, const Method* referrer, Thread*)
     move   $a2, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1041,7 +1041,7 @@
     .extern artGetObjStaticFromCode
 ENTRY art_quick_get_obj_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGetObjStaticFromCode       # (uint32_t field_idx, const Method* referrer, Thread*)
     move   $a2, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1053,7 +1053,7 @@
     .extern artGetBooleanInstanceFromCode
 ENTRY art_quick_get_boolean_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGetBooleanInstanceFromCode # (field_idx, Object*, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1065,7 +1065,7 @@
     .extern artGetByteInstanceFromCode
 ENTRY art_quick_get_byte_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGetByteInstanceFromCode    # (field_idx, Object*, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1077,7 +1077,7 @@
     .extern artGetCharInstanceFromCode
 ENTRY art_quick_get_char_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGetCharInstanceFromCode    # (field_idx, Object*, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1089,7 +1089,7 @@
     .extern artGetShortInstanceFromCode
 ENTRY art_quick_get_short_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGetShortInstanceFromCode   # (field_idx, Object*, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1101,7 +1101,7 @@
     .extern artGet32InstanceFromCode
 ENTRY art_quick_get32_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGet32InstanceFromCode      # (field_idx, Object*, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1113,7 +1113,7 @@
     .extern artGet64InstanceFromCode
 ENTRY art_quick_get64_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGet64InstanceFromCode      # (field_idx, Object*, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1125,7 +1125,7 @@
     .extern artGetObjInstanceFromCode
 ENTRY art_quick_get_obj_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artGetObjInstanceFromCode     # (field_idx, Object*, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_NO_EXCEPTION
@@ -1137,7 +1137,7 @@
     .extern artSet8StaticFromCode
 ENTRY art_quick_set8_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artSet8StaticFromCode         # (field_idx, new_val, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_ZERO
@@ -1149,7 +1149,7 @@
     .extern artSet16StaticFromCode
 ENTRY art_quick_set16_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artSet16StaticFromCode        # (field_idx, new_val, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_ZERO
@@ -1161,7 +1161,7 @@
     .extern artSet32StaticFromCode
 ENTRY art_quick_set32_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artSet32StaticFromCode        # (field_idx, new_val, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_ZERO
@@ -1174,7 +1174,7 @@
 ENTRY art_quick_set64_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
     move   $a2, $a1                      # pass new_val
-    lwu    $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a1, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artSet64StaticFromCode        # (field_idx, referrer, new_val, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_ZERO
@@ -1186,7 +1186,7 @@
     .extern artSetObjStaticFromCode
 ENTRY art_quick_set_obj_static
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a2, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artSetObjStaticFromCode       # (field_idx, new_val, referrer, Thread*)
     move   $a3, rSELF                    # pass Thread::Current
     RETURN_IF_ZERO
@@ -1198,7 +1198,7 @@
     .extern artSet8InstanceFromCode
 ENTRY art_quick_set8_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artSet8InstanceFromCode       # (field_idx, Object*, new_val, referrer, Thread*)
     move   $a4, rSELF                    # pass Thread::Current
     RETURN_IF_ZERO
@@ -1210,7 +1210,7 @@
     .extern artSet16InstanceFromCode
 ENTRY art_quick_set16_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artSet16InstanceFromCode      # (field_idx, Object*, new_val, referrer, Thread*)
     move   $a4, rSELF                    # pass Thread::Current
     RETURN_IF_ZERO
@@ -1222,7 +1222,7 @@
     .extern artSet32InstanceFromCode
 ENTRY art_quick_set32_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artSet32InstanceFromCode      # (field_idx, Object*, new_val, referrer, Thread*)
     move   $a4, rSELF                    # pass Thread::Current
     RETURN_IF_ZERO
@@ -1234,7 +1234,7 @@
     .extern artSet64InstanceFromCode
 ENTRY art_quick_set64_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artSet64InstanceFromCode      # (field_idx, Object*, new_val, referrer, Thread*)
     move   $a4, rSELF                    # pass Thread::Current
     RETURN_IF_ZERO
@@ -1246,7 +1246,7 @@
     .extern artSetObjInstanceFromCode
 ENTRY art_quick_set_obj_instance
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME    # save callee saves in case of GC
-    lwu    $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
+    ld     $a3, FRAME_SIZE_REFS_ONLY_CALLEE_SAVE($sp)  # pass referrer's Method*
     jal    artSetObjInstanceFromCode     # (field_idx, Object*, new_val, referrer, Thread*)
     move   $a4, rSELF                    # pass Thread::Current
     RETURN_IF_ZERO
@@ -1378,7 +1378,7 @@
     jal     artQuickResolutionTrampoline  # (Method* called, receiver, Thread*, SP)
     move    $a3, $sp               # pass $sp
     beq     $v0, $zero, 1f
-    lwu     $a0, 0($sp)            # load resolved method in $a0
+    ld      $a0, 0($sp)            # load resolved method in $a0
                                    # artQuickResolutionTrampoline puts resolved method in *SP
     RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
     move    $t9, $v0               # code pointer must be in $t9 to generate the global pointer
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 23b7cfa..62a6962 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -17,10 +17,10 @@
 #include <cstdio>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "entrypoints/quick/quick_entrypoints_enum.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/string-inl.h"
 #include "scoped_thread_state_change.h"
@@ -70,7 +70,7 @@
 
   // TODO: Set up a frame according to referrer's specs.
   size_t Invoke3WithReferrer(size_t arg0, size_t arg1, size_t arg2, uintptr_t code, Thread* self,
-                             mirror::ArtMethod* referrer) {
+                             ArtMethod* referrer) {
     // Push a transition back into managed code onto the linked list in thread.
     ManagedStack fragment;
     self->PushManagedStackFragment(&fragment);
@@ -420,7 +420,7 @@
 
   // TODO: Set up a frame according to referrer's specs.
   size_t Invoke3WithReferrerAndHidden(size_t arg0, size_t arg1, size_t arg2, uintptr_t code,
-                                      Thread* self, mirror::ArtMethod* referrer, size_t hidden) {
+                                      Thread* self, ArtMethod* referrer, size_t hidden) {
     // Push a transition back into managed code onto the linked list in thread.
     ManagedStack fragment;
     self->PushManagedStackFragment(&fragment);
@@ -776,7 +776,7 @@
 
   // Method with 32b arg0, 64b arg1
   size_t Invoke3UWithReferrer(size_t arg0, uint64_t arg1, uintptr_t code, Thread* self,
-                              mirror::ArtMethod* referrer) {
+                              ArtMethod* referrer) {
 #if (defined(__x86_64__) && !defined(__APPLE__)) || (defined(__mips__) && defined(__LP64__)) || \
     defined(__aarch64__)
     // Just pass through.
@@ -1282,7 +1282,8 @@
   {
     // Use an arbitrary method from c to use as referrer
     size_t result = Invoke3(static_cast<size_t>(c->GetDexTypeIndex()),    // type_idx
-                            reinterpret_cast<size_t>(c->GetVirtualMethod(0)),  // arbitrary
+                            // arbitrary
+                            reinterpret_cast<size_t>(c->GetVirtualMethod(0, sizeof(void*))),
                             0U,
                             StubTest::GetEntrypoint(self, kQuickAllocObject),
                             self);
@@ -1297,7 +1298,7 @@
   {
     // We can use null in the second argument as we do not need a method here (not used in
     // resolved/initialized cases)
-    size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), reinterpret_cast<size_t>(nullptr), 0U,
+    size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), 0u, 0U,
                             StubTest::GetEntrypoint(self, kQuickAllocObjectResolved),
                             self);
 
@@ -1311,7 +1312,7 @@
   {
     // We can use null in the second argument as we do not need a method here (not used in
     // resolved/initialized cases)
-    size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), reinterpret_cast<size_t>(nullptr), 0U,
+    size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), 0u, 0U,
                             StubTest::GetEntrypoint(self, kQuickAllocObjectInitialized),
                             self);
 
@@ -1367,7 +1368,7 @@
     }
     self->ClearException();
 
-    size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), reinterpret_cast<size_t>(nullptr), 0U,
+    size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), 0u, 0U,
                             StubTest::GetEntrypoint(self, kQuickAllocObjectInitialized),
                             self);
     EXPECT_TRUE(self->IsExceptionPending());
@@ -1417,7 +1418,8 @@
     // Use an arbitrary method from c to use as referrer
     size_t result = Invoke3(static_cast<size_t>(c->GetDexTypeIndex()),    // type_idx
                             10U,
-                            reinterpret_cast<size_t>(c_obj->GetVirtualMethod(0)),  // arbitrary
+                            // arbitrary
+                            reinterpret_cast<size_t>(c_obj->GetVirtualMethod(0, sizeof(void*))),
                             StubTest::GetEntrypoint(self, kQuickAllocArray),
                             self);
 
@@ -1554,7 +1556,7 @@
 
 
 static void GetSetBooleanStatic(ArtField* f, Thread* self,
-                                mirror::ArtMethod* referrer, StubTest* test)
+                                ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
     (defined(__x86_64__) && !defined(__APPLE__))
@@ -1584,7 +1586,7 @@
   std::cout << "Skipping set_boolean_static as I don't know how to do that on " << kRuntimeISA << std::endl;
 #endif
 }
-static void GetSetByteStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer,
+static void GetSetByteStatic(ArtField* f, Thread* self, ArtMethod* referrer,
                              StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
@@ -1616,7 +1618,7 @@
 
 
 static void GetSetBooleanInstance(Handle<mirror::Object>* obj, ArtField* f, Thread* self,
-                                  mirror::ArtMethod* referrer, StubTest* test)
+                                  ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
     (defined(__x86_64__) && !defined(__APPLE__))
@@ -1651,7 +1653,7 @@
 #endif
 }
 static void GetSetByteInstance(Handle<mirror::Object>* obj, ArtField* f,
-                             Thread* self, mirror::ArtMethod* referrer, StubTest* test)
+                             Thread* self, ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
     (defined(__x86_64__) && !defined(__APPLE__))
@@ -1685,7 +1687,7 @@
 #endif
 }
 
-static void GetSetCharStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer,
+static void GetSetCharStatic(ArtField* f, Thread* self, ArtMethod* referrer,
                              StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
@@ -1716,7 +1718,7 @@
 #endif
 }
 static void GetSetShortStatic(ArtField* f, Thread* self,
-                              mirror::ArtMethod* referrer, StubTest* test)
+                              ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
     (defined(__x86_64__) && !defined(__APPLE__))
@@ -1747,7 +1749,7 @@
 }
 
 static void GetSetCharInstance(Handle<mirror::Object>* obj, ArtField* f,
-                               Thread* self, mirror::ArtMethod* referrer, StubTest* test)
+                               Thread* self, ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
     (defined(__x86_64__) && !defined(__APPLE__))
@@ -1781,7 +1783,7 @@
 #endif
 }
 static void GetSetShortInstance(Handle<mirror::Object>* obj, ArtField* f,
-                             Thread* self, mirror::ArtMethod* referrer, StubTest* test)
+                             Thread* self, ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
     (defined(__x86_64__) && !defined(__APPLE__))
@@ -1815,7 +1817,7 @@
 #endif
 }
 
-static void GetSet32Static(ArtField* f, Thread* self, mirror::ArtMethod* referrer,
+static void GetSet32Static(ArtField* f, Thread* self, ArtMethod* referrer,
                            StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
@@ -1852,7 +1854,7 @@
 
 
 static void GetSet32Instance(Handle<mirror::Object>* obj, ArtField* f,
-                             Thread* self, mirror::ArtMethod* referrer, StubTest* test)
+                             Thread* self, ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
     (defined(__x86_64__) && !defined(__APPLE__))
@@ -1893,7 +1895,7 @@
     (defined(__x86_64__) && !defined(__APPLE__))
 
 static void set_and_check_static(uint32_t f_idx, mirror::Object* val, Thread* self,
-                                 mirror::ArtMethod* referrer, StubTest* test)
+                                 ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   test->Invoke3WithReferrer(static_cast<size_t>(f_idx),
                             reinterpret_cast<size_t>(val),
@@ -1912,7 +1914,7 @@
 }
 #endif
 
-static void GetSetObjStatic(ArtField* f, Thread* self, mirror::ArtMethod* referrer,
+static void GetSetObjStatic(ArtField* f, Thread* self, ArtMethod* referrer,
                             StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
@@ -1936,7 +1938,7 @@
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
     (defined(__x86_64__) && !defined(__APPLE__))
 static void set_and_check_instance(ArtField* f, mirror::Object* trg,
-                                   mirror::Object* val, Thread* self, mirror::ArtMethod* referrer,
+                                   mirror::Object* val, Thread* self, ArtMethod* referrer,
                                    StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()),
@@ -1960,7 +1962,7 @@
 #endif
 
 static void GetSetObjInstance(Handle<mirror::Object>* obj, ArtField* f,
-                              Thread* self, mirror::ArtMethod* referrer, StubTest* test)
+                              Thread* self, ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \
     (defined(__x86_64__) && !defined(__APPLE__))
@@ -1982,7 +1984,7 @@
 
 // TODO: Complete these tests for 32b architectures.
 
-static void GetSet64Static(ArtField* f, Thread* self, mirror::ArtMethod* referrer,
+static void GetSet64Static(ArtField* f, Thread* self, ArtMethod* referrer,
                            StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if (defined(__x86_64__) && !defined(__APPLE__)) || (defined(__mips__) && defined(__LP64__)) || \
@@ -2014,7 +2016,7 @@
 
 
 static void GetSet64Instance(Handle<mirror::Object>* obj, ArtField* f,
-                             Thread* self, mirror::ArtMethod* referrer, StubTest* test)
+                             Thread* self, ArtMethod* referrer, StubTest* test)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
 #if (defined(__x86_64__) && !defined(__APPLE__)) || (defined(__mips__) && defined(__LP64__)) || \
     defined(__aarch64__)
@@ -2060,11 +2062,11 @@
   CHECK(o != nullptr);
 
   ScopedObjectAccess soa(self);
-  StackHandleScope<4> hs(self);
+  StackHandleScope<3> hs(self);
   Handle<mirror::Object> obj(hs.NewHandle(soa.Decode<mirror::Object*>(o)));
   Handle<mirror::Class> c(hs.NewHandle(obj->GetClass()));
   // Need a method as a referrer
-  Handle<mirror::ArtMethod> m(hs.NewHandle(c->GetDirectMethod(0)));
+  ArtMethod* m = c->GetDirectMethod(0, sizeof(void*));
 
   // Play with it...
 
@@ -2079,27 +2081,27 @@
     }
     switch (type) {
       case Primitive::Type::kPrimBoolean:
-        GetSetBooleanStatic(f, self, m.Get(), test);
+        GetSetBooleanStatic(f, self, m, test);
         break;
       case Primitive::Type::kPrimByte:
-        GetSetByteStatic(f, self, m.Get(), test);
+        GetSetByteStatic(f, self, m, test);
         break;
       case Primitive::Type::kPrimChar:
-        GetSetCharStatic(f, self, m.Get(), test);
+        GetSetCharStatic(f, self, m, test);
         break;
       case Primitive::Type::kPrimShort:
-        GetSetShortStatic(f, self, m.Get(), test);
+        GetSetShortStatic(f, self, m, test);
         break;
       case Primitive::Type::kPrimInt:
-        GetSet32Static(f, self, m.Get(), test);
+        GetSet32Static(f, self, m, test);
         break;
       case Primitive::Type::kPrimLong:
-        GetSet64Static(f, self, m.Get(), test);
+        GetSet64Static(f, self, m, test);
         break;
       case Primitive::Type::kPrimNot:
         // Don't try array.
         if (f->GetTypeDescriptor()[0] != '[') {
-          GetSetObjStatic(f, self, m.Get(), test);
+          GetSetObjStatic(f, self, m, test);
         }
         break;
       default:
@@ -2118,27 +2120,27 @@
     }
     switch (type) {
       case Primitive::Type::kPrimBoolean:
-        GetSetBooleanInstance(&obj, f, self, m.Get(), test);
+        GetSetBooleanInstance(&obj, f, self, m, test);
         break;
       case Primitive::Type::kPrimByte:
-        GetSetByteInstance(&obj, f, self, m.Get(), test);
+        GetSetByteInstance(&obj, f, self, m, test);
         break;
       case Primitive::Type::kPrimChar:
-        GetSetCharInstance(&obj, f, self, m.Get(), test);
+        GetSetCharInstance(&obj, f, self, m, test);
         break;
       case Primitive::Type::kPrimShort:
-        GetSetShortInstance(&obj, f, self, m.Get(), test);
+        GetSetShortInstance(&obj, f, self, m, test);
         break;
       case Primitive::Type::kPrimInt:
-        GetSet32Instance(&obj, f, self, m.Get(), test);
+        GetSet32Instance(&obj, f, self, m, test);
         break;
       case Primitive::Type::kPrimLong:
-        GetSet64Instance(&obj, f, self, m.Get(), test);
+        GetSet64Instance(&obj, f, self, m, test);
         break;
       case Primitive::Type::kPrimNot:
         // Don't try array.
         if (f->GetTypeDescriptor()[0] != '[') {
-          GetSetObjInstance(&obj, f, self, m.Get(), test);
+          GetSetObjInstance(&obj, f, self, m, test);
         }
         break;
       default:
@@ -2235,17 +2237,18 @@
   ASSERT_NE(nullptr, arraylist_jclass);
   jmethodID arraylist_constructor = env->GetMethodID(arraylist_jclass, "<init>", "()V");
   ASSERT_NE(nullptr, arraylist_constructor);
-  jmethodID contains_jmethod = env->GetMethodID(arraylist_jclass, "contains", "(Ljava/lang/Object;)Z");
+  jmethodID contains_jmethod = env->GetMethodID(
+      arraylist_jclass, "contains", "(Ljava/lang/Object;)Z");
   ASSERT_NE(nullptr, contains_jmethod);
   jmethodID add_jmethod = env->GetMethodID(arraylist_jclass, "add", "(Ljava/lang/Object;)Z");
   ASSERT_NE(nullptr, add_jmethod);
 
-  // Get mirror representation.
-  Handle<mirror::ArtMethod> contains_amethod(hs.NewHandle(soa.DecodeMethod(contains_jmethod)));
+  // Get representation.
+  ArtMethod* contains_amethod = soa.DecodeMethod(contains_jmethod);
 
   // Patch up ArrayList.contains.
-  if (contains_amethod.Get()->GetEntryPointFromQuickCompiledCode() == nullptr) {
-    contains_amethod.Get()->SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>(
+  if (contains_amethod->GetEntryPointFromQuickCompiledCode() == nullptr) {
+    contains_amethod->SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>(
         StubTest::GetEntrypoint(self, kQuickQuickToInterpreterBridge)));
   }
 
@@ -2254,11 +2257,12 @@
   // Load List and used methods (JNI).
   jclass list_jclass = env->FindClass("java/util/List");
   ASSERT_NE(nullptr, list_jclass);
-  jmethodID inf_contains_jmethod = env->GetMethodID(list_jclass, "contains", "(Ljava/lang/Object;)Z");
+  jmethodID inf_contains_jmethod = env->GetMethodID(
+      list_jclass, "contains", "(Ljava/lang/Object;)Z");
   ASSERT_NE(nullptr, inf_contains_jmethod);
 
   // Get mirror representation.
-  Handle<mirror::ArtMethod> inf_contains(hs.NewHandle(soa.DecodeMethod(inf_contains_jmethod)));
+  ArtMethod* inf_contains = soa.DecodeMethod(inf_contains_jmethod);
 
   // Object
 
@@ -2287,8 +2291,8 @@
       Invoke3WithReferrerAndHidden(0U, reinterpret_cast<size_t>(array_list.Get()),
                                    reinterpret_cast<size_t>(obj.Get()),
                                    StubTest::GetEntrypoint(self, kQuickQuickImtConflictTrampoline),
-                                   self, contains_amethod.Get(),
-                                   static_cast<size_t>(inf_contains.Get()->GetDexMethodIndex()));
+                                   self, contains_amethod,
+                                   static_cast<size_t>(inf_contains->GetDexMethodIndex()));
 
   ASSERT_FALSE(self->IsExceptionPending());
   EXPECT_EQ(static_cast<size_t>(JNI_FALSE), result);
@@ -2301,33 +2305,31 @@
 
   // Contains.
 
-  result = Invoke3WithReferrerAndHidden(0U, reinterpret_cast<size_t>(array_list.Get()),
-                                        reinterpret_cast<size_t>(obj.Get()),
-                                        StubTest::GetEntrypoint(self, kQuickQuickImtConflictTrampoline),
-                                        self, contains_amethod.Get(),
-                                        static_cast<size_t>(inf_contains.Get()->GetDexMethodIndex()));
+  result = Invoke3WithReferrerAndHidden(
+      0U, reinterpret_cast<size_t>(array_list.Get()), reinterpret_cast<size_t>(obj.Get()),
+      StubTest::GetEntrypoint(self, kQuickQuickImtConflictTrampoline), self, contains_amethod,
+      static_cast<size_t>(inf_contains->GetDexMethodIndex()));
 
   ASSERT_FALSE(self->IsExceptionPending());
   EXPECT_EQ(static_cast<size_t>(JNI_TRUE), result);
 
   // 2. regular interface trampoline
 
-  result = Invoke3WithReferrer(static_cast<size_t>(inf_contains.Get()->GetDexMethodIndex()),
+  result = Invoke3WithReferrer(static_cast<size_t>(inf_contains->GetDexMethodIndex()),
                                reinterpret_cast<size_t>(array_list.Get()),
                                reinterpret_cast<size_t>(obj.Get()),
                                StubTest::GetEntrypoint(self,
                                    kQuickInvokeInterfaceTrampolineWithAccessCheck),
-                               self, contains_amethod.Get());
+                               self, contains_amethod);
 
   ASSERT_FALSE(self->IsExceptionPending());
   EXPECT_EQ(static_cast<size_t>(JNI_TRUE), result);
 
-  result = Invoke3WithReferrer(static_cast<size_t>(inf_contains.Get()->GetDexMethodIndex()),
-                               reinterpret_cast<size_t>(array_list.Get()),
-                               reinterpret_cast<size_t>(array_list.Get()),
-                               StubTest::GetEntrypoint(self,
-                                   kQuickInvokeInterfaceTrampolineWithAccessCheck),
-                               self, contains_amethod.Get());
+  result = Invoke3WithReferrer(
+      static_cast<size_t>(inf_contains->GetDexMethodIndex()),
+      reinterpret_cast<size_t>(array_list.Get()), reinterpret_cast<size_t>(array_list.Get()),
+      StubTest::GetEntrypoint(self, kQuickInvokeInterfaceTrampolineWithAccessCheck), self,
+      contains_amethod);
 
   ASSERT_FALSE(self->IsExceptionPending());
   EXPECT_EQ(static_cast<size_t>(JNI_FALSE), result);
diff --git a/runtime/arch/x86/context_x86.cc b/runtime/arch/x86/context_x86.cc
index 06bae75..7096c82aa 100644
--- a/runtime/arch/x86/context_x86.cc
+++ b/runtime/arch/x86/context_x86.cc
@@ -16,8 +16,8 @@
 
 #include "context_x86.h"
 
+#include "art_method-inl.h"
 #include "base/bit_utils.h"
-#include "mirror/art_method-inl.h"
 #include "quick/quick_method_frame_info.h"
 
 namespace art {
@@ -35,7 +35,7 @@
 }
 
 void X86Context::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
   int spill_pos = 0;
 
diff --git a/runtime/arch/x86/fault_handler_x86.cc b/runtime/arch/x86/fault_handler_x86.cc
index 2de69aa..d7c4cb1 100644
--- a/runtime/arch/x86/fault_handler_x86.cc
+++ b/runtime/arch/x86/fault_handler_x86.cc
@@ -16,13 +16,14 @@
 
 
 #include "fault_handler.h"
+
 #include <sys/ucontext.h>
+
+#include "art_method-inl.h"
 #include "base/macros.h"
 #include "globals.h"
 #include "base/logging.h"
 #include "base/hex_dump.h"
-#include "mirror/art_method.h"
-#include "mirror/art_method-inl.h"
 #include "thread.h"
 #include "thread-inl.h"
 
@@ -248,7 +249,7 @@
 }
 
 void FaultManager::GetMethodAndReturnPcAndSp(siginfo_t* siginfo, void* context,
-                                             mirror::ArtMethod** out_method,
+                                             ArtMethod** out_method,
                                              uintptr_t* out_return_pc, uintptr_t* out_sp) {
   struct ucontext* uc = reinterpret_cast<struct ucontext*>(context);
   *out_sp = static_cast<uintptr_t>(uc->CTX_ESP);
@@ -267,10 +268,10 @@
       reinterpret_cast<uint8_t*>(*out_sp) - GetStackOverflowReservedBytes(kX86));
 #endif
   if (overflow_addr == fault_addr) {
-    *out_method = reinterpret_cast<mirror::ArtMethod*>(uc->CTX_METHOD);
+    *out_method = reinterpret_cast<ArtMethod*>(uc->CTX_METHOD);
   } else {
     // The method is at the top of the stack.
-    *out_method = (reinterpret_cast<StackReference<mirror::ArtMethod>* >(*out_sp)[0]).AsMirrorPtr();
+    *out_method = *reinterpret_cast<ArtMethod**>(*out_sp);
   }
 
   uint8_t* pc = reinterpret_cast<uint8_t*>(uc->CTX_EIP);
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 8207360..e0397cc 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -472,7 +472,7 @@
     // Nothing left to load.
 .Lgpr_setup_finished:
     mov 20(%ebp), %eax            // move method pointer into eax
-    call *MIRROR_ART_METHOD_QUICK_CODE_OFFSET_32(%eax) // call the method
+    call *ART_METHOD_QUICK_CODE_OFFSET_32(%eax) // call the method
     mov %ebp, %esp                // restore stack pointer
     CFI_DEF_CFA_REGISTER(esp)
     POP edi                       // pop edi
@@ -589,7 +589,7 @@
     // Nothing left to load.
 .Lgpr_setup_finished2:
     mov 20(%ebp), %eax            // move method pointer into eax
-    call *MIRROR_ART_METHOD_QUICK_CODE_OFFSET_32(%eax) // call the method
+    call *ART_METHOD_QUICK_CODE_OFFSET_32(%eax) // call the method
     mov %ebp, %esp                // restore stack pointer
     CFI_DEF_CFA_REGISTER(esp)
     POP edi                       // pop edi
diff --git a/runtime/arch/x86_64/context_x86_64.cc b/runtime/arch/x86_64/context_x86_64.cc
index 2c4532c..1fe2ef8 100644
--- a/runtime/arch/x86_64/context_x86_64.cc
+++ b/runtime/arch/x86_64/context_x86_64.cc
@@ -16,8 +16,8 @@
 
 #include "context_x86_64.h"
 
+#include "art_method-inl.h"
 #include "base/bit_utils.h"
-#include "mirror/art_method-inl.h"
 #include "quick/quick_method_frame_info.h"
 
 namespace art {
@@ -35,7 +35,7 @@
 }
 
 void X86_64Context::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
   int spill_pos = 0;
 
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 7bb18a4..48f59f3 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -57,7 +57,7 @@
     PUSH r12  // Callee save.
     PUSH rbp  // Callee save.
     PUSH rbx  // Callee save.
-    // Create space for FPR args, plus space for StackReference<ArtMethod>.
+    // Create space for FPR args, plus space for ArtMethod*.
     subq MACRO_LITERAL(4 * 8 + 8), %rsp
     CFI_ADJUST_CFA_OFFSET(4 * 8 + 8)
     // Save FPRs.
@@ -67,7 +67,7 @@
     movq %xmm15, 32(%rsp)
     // R10 := ArtMethod* for save all callee save frame method.
     THIS_LOAD_REQUIRES_READ_BARRIER
-    movl RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10d
+    movq RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
     // Store ArtMethod* to bottom of stack.
     movq %r10, 0(%rsp)
     // Store rsp as the top quick frame.
@@ -100,7 +100,7 @@
     PUSH r12  // Callee save.
     PUSH rbp  // Callee save.
     PUSH rbx  // Callee save.
-    // Create space for FPR args, plus space for StackReference<ArtMethod>.
+    // Create space for FPR args, plus space for ArtMethod*.
     subq LITERAL(8 + 4 * 8), %rsp
     CFI_ADJUST_CFA_OFFSET(8 + 4 * 8)
     // Save FPRs.
@@ -110,7 +110,7 @@
     movq %xmm15, 32(%rsp)
     // R10 := ArtMethod* for refs only callee save frame method.
     THIS_LOAD_REQUIRES_READ_BARRIER
-    movl RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10d
+    movq RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
     // Store ArtMethod* to bottom of stack.
     movq %r10, 0(%rsp)
     // Store rsp as the stop quick frame.
@@ -164,13 +164,12 @@
     PUSH rbx  // Callee save.
     PUSH rdx  // Quick arg 2.
     PUSH rcx  // Quick arg 3.
-    // Create space for FPR args and create 2 slots, 1 of padding and 1 for the
-    // StackReference<ArtMethod>.
+    // Create space for FPR args and create 2 slots for ArtMethod*.
     subq MACRO_LITERAL(80 + 4 * 8), %rsp
     CFI_ADJUST_CFA_OFFSET(80 + 4 * 8)
     // R10 := ArtMethod* for ref and args callee save frame method.
     THIS_LOAD_REQUIRES_READ_BARRIER
-    movl RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10d
+    movq RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET(%r10), %r10
     // Save FPRs.
     movq %xmm0, 16(%rsp)
     movq %xmm1, 24(%rsp)
@@ -210,8 +209,7 @@
     PUSH rbx  // Callee save.
     PUSH rdx  // Quick arg 2.
     PUSH rcx  // Quick arg 3.
-    // Create space for FPR args and create 2 slots, 1 of padding and 1 for the
-    // StackReference<ArtMethod>.
+    // Create space for FPR args and create 2 slots for ArtMethod*.
     subq LITERAL(80 + 4 * 8), %rsp
     CFI_ADJUST_CFA_OFFSET(80 + 4 * 8)
     // Save FPRs.
@@ -504,13 +502,13 @@
 #if (STACK_REFERENCE_SIZE != 4)
 #error "STACK_REFERENCE_SIZE(X86_64) size not as expected."
 #endif
-    movl LITERAL(0), (%rsp)       // Store null for method*
+    movq LITERAL(0), (%rsp)       // Store null for method*
 
     movl %r10d, %ecx              // Place size of args in rcx.
     movq %rdi, %rax               // rax := method to be called
     movq %rsi, %r11               // r11 := arg_array
-    leaq 4(%rsp), %rdi            // rdi is pointing just above the StackReference<method> in the
-                                  // stack arguments.
+    leaq 8(%rsp), %rdi            // rdi is pointing just above the ArtMethod* in the stack
+                                  // arguments.
     // Copy arg array into stack.
     rep movsb                     // while (rcx--) { *rdi++ = *rsi++ }
     leaq 1(%r9), %r10             // r10 := shorty + 1  ; ie skip return arg character
@@ -522,7 +520,7 @@
     LOOP_OVER_SHORTY_LOADING_GPRS r8, r8d, .Lgpr_setup_finished
     LOOP_OVER_SHORTY_LOADING_GPRS r9, r9d, .Lgpr_setup_finished
 .Lgpr_setup_finished:
-    call *MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
+    call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
     movq %rbp, %rsp               // Restore stack pointer.
     POP r15                       // Pop r15
     POP r14                       // Pop r14
@@ -598,12 +596,12 @@
 #if (STACK_REFERENCE_SIZE != 4)
 #error "STACK_REFERENCE_SIZE(X86_64) size not as expected."
 #endif
-    movl LITERAL(0), (%rsp)        // Store null for method*
+    movq LITERAL(0), (%rsp)        // Store null for method*
 
     movl %r10d, %ecx               // Place size of args in rcx.
     movq %rdi, %rax                // rax := method to be called
     movq %rsi, %r11                // r11 := arg_array
-    leaq 4(%rsp), %rdi             // rdi is pointing just above the StackReference<method> in the
+    leaq 8(%rsp), %rdi             // rdi is pointing just above the ArtMethod* in the
                                    // stack arguments.
     // Copy arg array into stack.
     rep movsb                      // while (rcx--) { *rdi++ = *rsi++ }
@@ -615,7 +613,7 @@
     LOOP_OVER_SHORTY_LOADING_GPRS r8, r8d, .Lgpr_setup_finished2
     LOOP_OVER_SHORTY_LOADING_GPRS r9, r9d, .Lgpr_setup_finished2
 .Lgpr_setup_finished2:
-    call *MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
+    call *ART_METHOD_QUICK_CODE_OFFSET_64(%rdi) // Call the method.
     movq %rbp, %rsp                // Restore stack pointer.
     POP r15                        // Pop r15
     POP r14                        // Pop r14
@@ -749,7 +747,7 @@
 
 MACRO3(ONE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
     DEFINE_FUNCTION VAR(c_name, 0)
-    movl 8(%rsp), %esi                  // pass referrer
+    movq 8(%rsp), %rsi                  // pass referrer
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
                                         // arg0 is in rdi
     movq %gs:THREAD_SELF_OFFSET, %rdx   // pass Thread::Current()
@@ -761,7 +759,7 @@
 
 MACRO3(TWO_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
     DEFINE_FUNCTION VAR(c_name, 0)
-    movl 8(%rsp), %edx                  // pass referrer
+    movq 8(%rsp), %rdx                  // pass referrer
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
                                         // arg0 and arg1 are in rdi/rsi
     movq %gs:THREAD_SELF_OFFSET, %rcx   // pass Thread::Current()
@@ -773,7 +771,7 @@
 
 MACRO3(THREE_ARG_REF_DOWNCALL, c_name, cxx_name, return_macro)
     DEFINE_FUNCTION VAR(c_name, 0)
-    movl 8(%rsp), %ecx                  // pass referrer
+    movq 8(%rsp), %rcx                  // pass referrer
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
                                         // arg0, arg1, and arg2 are in rdi/rsi/rdx
     movq %gs:THREAD_SELF_OFFSET, %r8    // pass Thread::Current()
@@ -920,7 +918,7 @@
     // Fast path tlab allocation.
     // RDI: uint32_t type_idx, RSI: ArtMethod*
     // RDX, RCX, R8, R9: free. RAX: return val.
-    movl MIRROR_ART_METHOD_DEX_CACHE_TYPES_OFFSET(%rsi), %edx  // Load dex cache resolved types array
+    movl ART_METHOD_DEX_CACHE_TYPES_OFFSET(%rsi), %edx  // Load dex cache resolved types array
                                                                // Load the class
     movl MIRROR_OBJECT_ARRAY_DATA_OFFSET(%rdx, %rdi, MIRROR_OBJECT_ARRAY_COMPONENT_SIZE), %edx
     testl %edx, %edx                                           // Check null class
@@ -1307,7 +1305,7 @@
 // This is singled out as the argument order is different.
 DEFINE_FUNCTION art_quick_set64_static
     movq %rsi, %rdx                      // pass new_val
-    movl 8(%rsp), %esi                   // pass referrer
+    movq 8(%rsp), %rsi                   // pass referrer
     SETUP_REFS_ONLY_CALLEE_SAVE_FRAME
                                          // field_idx is in rdi
     movq %gs:THREAD_SELF_OFFSET, %rcx    // pass Thread::Current()
@@ -1391,7 +1389,6 @@
  * | XMM2              |    float arg 3
  * | XMM1              |    float arg 2
  * | XMM0              |    float arg 1
- * | Padding           |
  * | RDI/Method*       |  <- sp
  * #-------------------#
  * | Scratch Alloca    |    5K scratch space
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index 4991ad7..ee51ec9 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -328,6 +328,11 @@
   return name;
 }
 
+template<typename RootVisitorType>
+inline void ArtField::VisitRoots(RootVisitorType& visitor) {
+  visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_ART_FIELD_INL_H_
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index 47d5a76..e4a5834 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -20,6 +20,7 @@
 #include "class_linker-inl.h"
 #include "gc/accounting/card_table-inl.h"
 #include "handle_scope.h"
+#include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "runtime.h"
@@ -46,10 +47,6 @@
   offset_ = num_bytes.Uint32Value();
 }
 
-void ArtField::VisitRoots(RootVisitor* visitor) {
-  declaring_class_.VisitRoot(visitor, RootInfo(kRootStickyClass));
-}
-
 ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset) {
   DCHECK(klass != nullptr);
   auto* instance_fields = klass->GetIFields();
diff --git a/runtime/art_field.h b/runtime/art_field.h
index 9d3dbd9..7a03723 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -38,7 +38,7 @@
 class String;
 }  // namespace mirror
 
-class ArtField {
+class ArtField FINAL {
  public:
   ArtField();
 
@@ -151,8 +151,8 @@
   void SetObj(mirror::Object* object, mirror::Object* new_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void VisitRoots(RootVisitor* visitor)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<typename RootVisitorType>
+  void VisitRoots(RootVisitorType& visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsVolatile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return (GetAccessFlags() & kAccVolatile) != 0;
diff --git a/runtime/mirror/art_method-inl.h b/runtime/art_method-inl.h
similarity index 63%
rename from runtime/mirror/art_method-inl.h
rename to runtime/art_method-inl.h
index 7c8067a..ad1ecea 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-#ifndef ART_RUNTIME_MIRROR_ART_METHOD_INL_H_
-#define ART_RUNTIME_MIRROR_ART_METHOD_INL_H_
+#ifndef ART_RUNTIME_ART_METHOD_INL_H_
+#define ART_RUNTIME_ART_METHOD_INL_H_
 
 #include "art_method.h"
 
 #include "art_field.h"
-#include "class.h"
-#include "class_linker-inl.h"
-#include "dex_cache.h"
 #include "dex_file.h"
 #include "dex_file-inl.h"
-#include "object-inl.h"
-#include "object_array.h"
+#include "gc_root-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/dex_cache.h"
+#include "mirror/object-inl.h"
+#include "mirror/object_array.h"
 #include "oat.h"
 #include "quick/quick_method_frame_info.h"
 #include "read_barrier-inl.h"
@@ -34,73 +34,82 @@
 #include "utils.h"
 
 namespace art {
-namespace mirror {
 
-inline uint32_t ArtMethod::ClassSize() {
-  uint32_t vtable_entries = Object::kVTableLength;
-  return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
+inline mirror::Class* ArtMethod::GetDeclaringClassUnchecked() {
+  return declaring_class_.Read();
 }
 
-template<ReadBarrierOption kReadBarrierOption>
-inline Class* ArtMethod::GetJavaLangReflectArtMethod() {
-  DCHECK(!java_lang_reflect_ArtMethod_.IsNull());
-  return java_lang_reflect_ArtMethod_.Read<kReadBarrierOption>();
+inline mirror::Class* ArtMethod::GetDeclaringClassNoBarrier() {
+  return declaring_class_.Read<kWithoutReadBarrier>();
 }
 
-inline Class* ArtMethod::GetDeclaringClass() {
-  Class* result = GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_));
-  DCHECK(result != nullptr) << this;
-  DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this;
+inline mirror::Class* ArtMethod::GetDeclaringClass() {
+  mirror::Class* result = GetDeclaringClassUnchecked();
+  if (kIsDebugBuild) {
+    if (!IsRuntimeMethod()) {
+      CHECK(result != nullptr) << this;
+      CHECK(result->IsIdxLoaded() || result->IsErroneous())
+          << result->GetStatus() << " " << PrettyClass(result);
+    } else {
+      CHECK(result == nullptr) << this;
+    }
+  }
   return result;
 }
 
-inline void ArtMethod::SetDeclaringClass(Class *new_declaring_class) {
-  SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, declaring_class_),
-                        new_declaring_class);
+inline void ArtMethod::SetDeclaringClass(mirror::Class* new_declaring_class) {
+  declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
 }
 
 inline uint32_t ArtMethod::GetAccessFlags() {
-  DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous());
-  return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, access_flags_));
+  DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsIdxLoaded() ||
+         GetDeclaringClass()->IsErroneous());
+  return access_flags_;
 }
 
 inline uint16_t ArtMethod::GetMethodIndex() {
-  DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
-  return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_));
+  DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsResolved() ||
+         GetDeclaringClass()->IsErroneous());
+  return method_index_;
 }
 
 inline uint16_t ArtMethod::GetMethodIndexDuringLinking() {
-  return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_));
+  return method_index_;
 }
 
 inline uint32_t ArtMethod::GetDexMethodIndex() {
-  DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
-  return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_));
+  DCHECK(IsRuntimeMethod() || GetDeclaringClass()->IsIdxLoaded() ||
+         GetDeclaringClass()->IsErroneous());
+  return dex_method_index_;
 }
 
-inline ObjectArray<ArtMethod>* ArtMethod::GetDexCacheResolvedMethods() {
-  return GetFieldObject<ObjectArray<ArtMethod>>(
-      OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_));
+inline mirror::PointerArray* ArtMethod::GetDexCacheResolvedMethods() {
+  return dex_cache_resolved_methods_.Read();
 }
 
-inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index) {
-  ArtMethod* method = GetDexCacheResolvedMethods()->Get(method_index);
-  if (method != nullptr && !method->GetDeclaringClass()->IsErroneous()) {
-    return method;
-  } else {
-    return nullptr;
+inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index, size_t ptr_size) {
+  auto* method = GetDexCacheResolvedMethods()->GetElementPtrSize<ArtMethod*>(
+      method_index, ptr_size);
+  if (LIKELY(method != nullptr)) {
+    auto* declaring_class = method->GetDeclaringClass();
+    if (LIKELY(declaring_class == nullptr || !declaring_class->IsErroneous())) {
+      return method;
+    }
   }
+  return nullptr;
 }
 
-inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method) {
-  GetDexCacheResolvedMethods()->Set<false>(method_idx, new_method);
+inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method,
+                                                 size_t ptr_size) {
+  DCHECK(new_method == nullptr || new_method->GetDeclaringClass() != nullptr);
+  GetDexCacheResolvedMethods()->SetElementPtrSize(method_idx, new_method, ptr_size);
 }
 
 inline bool ArtMethod::HasDexCacheResolvedMethods() {
   return GetDexCacheResolvedMethods() != nullptr;
 }
 
-inline bool ArtMethod::HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache) {
+inline bool ArtMethod::HasSameDexCacheResolvedMethods(mirror::PointerArray* other_cache) {
   return GetDexCacheResolvedMethods() == other_cache;
 }
 
@@ -108,20 +117,15 @@
   return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods();
 }
 
-
-inline ObjectArray<Class>* ArtMethod::GetDexCacheResolvedTypes() {
-  return GetFieldObject<ObjectArray<Class>>(
-      OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_));
+inline mirror::ObjectArray<mirror::Class>* ArtMethod::GetDexCacheResolvedTypes() {
+  return dex_cache_resolved_types_.Read();
 }
 
 template <bool kWithCheck>
-inline Class* ArtMethod::GetDexCacheResolvedType(uint32_t type_index) {
-  Class* klass;
-  if (kWithCheck) {
-    klass = GetDexCacheResolvedTypes()->Get(type_index);
-  } else {
-    klass = GetDexCacheResolvedTypes()->GetWithoutChecks(type_index);
-  }
+inline mirror::Class* ArtMethod::GetDexCacheResolvedType(uint32_t type_index) {
+  mirror::Class* klass = kWithCheck ?
+      GetDexCacheResolvedTypes()->Get(type_index) :
+      GetDexCacheResolvedTypes()->GetWithoutChecks(type_index);
   return (klass != nullptr && !klass->IsErroneous()) ? klass : nullptr;
 }
 
@@ -129,7 +133,8 @@
   return GetDexCacheResolvedTypes() != nullptr;
 }
 
-inline bool ArtMethod::HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache) {
+inline bool ArtMethod::HasSameDexCacheResolvedTypes(
+    mirror::ObjectArray<mirror::Class>* other_cache) {
   return GetDexCacheResolvedTypes() == other_cache;
 }
 
@@ -165,7 +170,7 @@
     case kDirect:
       return !IsDirect() || IsStatic();
     case kVirtual: {
-      Class* methods_class = GetDeclaringClass();
+      mirror::Class* methods_class = GetDeclaringClass();
       return IsDirect() || (methods_class->IsInterface() && !IsMiranda());
     }
     case kSuper:
@@ -173,7 +178,7 @@
       // Interface methods cannot be invoked with invoke-super.
       return IsConstructor() || IsStatic() || GetDeclaringClass()->IsInterface();
     case kInterface: {
-      Class* methods_class = GetDeclaringClass();
+      mirror::Class* methods_class = GetDeclaringClass();
       return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
     }
     default:
@@ -237,7 +242,8 @@
   DCHECK(code_pointer != nullptr);
   uint32_t offset =
       reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].vmap_table_offset_;
-  const void* data = reinterpret_cast<const void*>(reinterpret_cast<const uint8_t*>(code_pointer) - offset);
+  const void* data =
+      reinterpret_cast<const void*>(reinterpret_cast<const uint8_t*>(code_pointer) - offset);
   return CodeInfo(data);
 }
 
@@ -261,7 +267,7 @@
 }
 
 inline bool ArtMethod::IsRuntimeMethod() {
-  return GetDexMethodIndex() == DexFile::kDexNoIndex;
+  return dex_method_index_ == DexFile::kDexNoIndex;
 }
 
 inline bool ArtMethod::IsCalleeSaveMethod() {
@@ -317,48 +323,48 @@
 }
 
 inline const char* ArtMethod::GetDeclaringClassDescriptor() {
-  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
-  uint32_t dex_method_idx = method->GetDexMethodIndex();
+  uint32_t dex_method_idx = GetDexMethodIndex();
   if (UNLIKELY(dex_method_idx == DexFile::kDexNoIndex)) {
     return "<runtime method>";
   }
-  const DexFile* dex_file = method->GetDexFile();
+  DCHECK(!IsProxyMethod());
+  const DexFile* dex_file = 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);
+  DCHECK(!IsProxyMethod());
+  const DexFile* dex_file = GetDexFile();
+  return dex_file->GetMethodShorty(dex_file->GetMethodId(GetDexMethodIndex()), out_length);
 }
 
 inline const Signature ArtMethod::GetSignature() {
-  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
-  uint32_t dex_method_idx = method->GetDexMethodIndex();
+  uint32_t dex_method_idx = GetDexMethodIndex();
   if (dex_method_idx != DexFile::kDexNoIndex) {
-    const DexFile* dex_file = method->GetDexFile();
+    DCHECK(!IsProxyMethod());
+    const DexFile* dex_file = GetDexFile();
     return dex_file->GetMethodSignature(dex_file->GetMethodId(dex_method_idx));
   }
   return Signature::NoSignature();
 }
 
 inline const char* ArtMethod::GetName() {
-  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
-  uint32_t dex_method_idx = method->GetDexMethodIndex();
+  uint32_t dex_method_idx = GetDexMethodIndex();
   if (LIKELY(dex_method_idx != DexFile::kDexNoIndex)) {
-    const DexFile* dex_file = method->GetDexFile();
+    DCHECK(!IsProxyMethod());
+    const DexFile* dex_file = GetDexFile();
     return dex_file->GetMethodName(dex_file->GetMethodId(dex_method_idx));
   }
-  Runtime* runtime = Runtime::Current();
-  if (method == runtime->GetResolutionMethod()) {
+  Runtime* const runtime = Runtime::Current();
+  if (this == runtime->GetResolutionMethod()) {
     return "<runtime internal resolution method>";
-  } else if (method == runtime->GetImtConflictMethod()) {
+  } else if (this == runtime->GetImtConflictMethod()) {
     return "<runtime internal imt conflict method>";
-  } else if (method == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) {
+  } else if (this == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) {
     return "<runtime internal callee-save all registers method>";
-  } else if (method == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) {
+  } else if (this == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) {
     return "<runtime internal callee-save reference registers method>";
-  } else if (method == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) {
+  } else if (this == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) {
     return "<runtime internal callee-save reference and argument registers method>";
   } else {
     return "<unknown runtime internal method>";
@@ -370,92 +376,96 @@
 }
 
 inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) {
-  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
-  return method->GetDexCacheResolvedType(type_idx) != nullptr;
+  DCHECK(!IsProxyMethod());
+  return GetDexCacheResolvedType(type_idx) != nullptr;
 }
 
 inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
-  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
+  DCHECK(!IsProxyMethod());
   if (dex_pc == DexFile::kDexNoIndex) {
-    return method->IsNative() ? -2 : -1;
+    return IsNative() ? -2 : -1;
   }
-  return method->GetDexFile()->GetLineNumFromPC(method, dex_pc);
+  return GetDexFile()->GetLineNumFromPC(this, 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()));
+  DCHECK(!IsProxyMethod());
+  const DexFile* dex_file = GetDexFile();
+  return dex_file->GetMethodPrototype(dex_file->GetMethodId(GetDexMethodIndex()));
 }
 
 inline const DexFile::TypeList* ArtMethod::GetParameterTypeList() {
-  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
-  const DexFile* dex_file = method->GetDexFile();
+  DCHECK(!IsProxyMethod());
+  const DexFile* dex_file = GetDexFile();
   const DexFile::ProtoId& proto = dex_file->GetMethodPrototype(
-      dex_file->GetMethodId(method->GetDexMethodIndex()));
+      dex_file->GetMethodId(GetDexMethodIndex()));
   return dex_file->GetProtoParameters(proto);
 }
 
 inline const char* ArtMethod::GetDeclaringClassSourceFile() {
-  return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetSourceFile();
+  DCHECK(!IsProxyMethod());
+  return GetDeclaringClass()->GetSourceFile();
 }
 
 inline uint16_t ArtMethod::GetClassDefIndex() {
-  return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexClassDefIndex();
+  DCHECK(!IsProxyMethod());
+  return GetDeclaringClass()->GetDexClassDefIndex();
 }
 
 inline const DexFile::ClassDef& ArtMethod::GetClassDef() {
-  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
-  return method->GetDexFile()->GetClassDef(GetClassDefIndex());
+  DCHECK(!IsProxyMethod());
+  return 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());
+  DCHECK(!IsProxyMethod());
+  const DexFile* dex_file = GetDexFile();
+  const DexFile::MethodId& method_id = dex_file->GetMethodId(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();
+  DCHECK(!IsProxyMethod());
+  const DexFile* dex_file = GetDexFile();
   return dex_file->GetTypeDescriptor(dex_file->GetTypeId(type_idx));
 }
 
 inline mirror::ClassLoader* ArtMethod::GetClassLoader() {
-  return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetClassLoader();
+  DCHECK(!IsProxyMethod());
+  return GetDeclaringClass()->GetClassLoader();
 }
 
 inline mirror::DexCache* ArtMethod::GetDexCache() {
-  return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache();
+  DCHECK(!IsProxyMethod());
+  return GetDeclaringClass()->GetDexCache();
 }
 
 inline bool ArtMethod::IsProxyMethod() {
   return GetDeclaringClass()->IsProxyClass();
 }
 
-inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy() {
+inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(size_t pointer_size) {
   if (LIKELY(!IsProxyMethod())) {
     return this;
   }
   mirror::Class* klass = GetDeclaringClass();
-  mirror::ArtMethod* interface_method = GetDexCacheResolvedMethods()->Get(GetDexMethodIndex());
+  auto interface_method = GetDexCacheResolvedMethods()->GetElementPtrSize<ArtMethod*>(
+      GetDexMethodIndex(), pointer_size);
   DCHECK(interface_method != nullptr);
   DCHECK_EQ(interface_method,
             Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this));
   return interface_method;
 }
 
-inline void ArtMethod::SetDexCacheResolvedMethods(ObjectArray<ArtMethod>* new_dex_cache_methods) {
-  SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_methods_),
-                        new_dex_cache_methods);
+inline void ArtMethod::SetDexCacheResolvedMethods(mirror::PointerArray* new_dex_cache_methods) {
+  dex_cache_resolved_methods_ = GcRoot<mirror::PointerArray>(new_dex_cache_methods);
 }
 
-inline void ArtMethod::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_classes) {
-  SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_),
-                        new_dex_cache_classes);
+inline void ArtMethod::SetDexCacheResolvedTypes(
+    mirror::ObjectArray<mirror::Class>* new_dex_cache_types) {
+  dex_cache_resolved_types_ = GcRoot<mirror::ObjectArray<mirror::Class>>(new_dex_cache_types);
 }
 
 inline mirror::Class* ArtMethod::GetReturnType(bool resolve) {
@@ -472,17 +482,23 @@
   return type;
 }
 
-inline void ArtMethod::CheckObjectSizeEqualsMirrorSize() {
-  // Using the default, check the class object size to make sure it matches the size of the
-  // object.
-  size_t this_size = sizeof(*this);
-#ifdef ART_METHOD_HAS_PADDING_FIELD_ON_64_BIT
-  this_size += sizeof(void*) - sizeof(uint32_t);
-#endif
-  DCHECK_EQ(GetClass()->GetObjectSize(), this_size);
+template<typename RootVisitorType>
+void ArtMethod::VisitRoots(RootVisitorType& visitor) {
+  visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
+  visitor.VisitRoot(dex_cache_resolved_methods_.AddressWithoutBarrier());
+  visitor.VisitRoot(dex_cache_resolved_types_.AddressWithoutBarrier());
 }
 
-}  // namespace mirror
+inline void ArtMethod::CopyFrom(const ArtMethod* src, size_t image_pointer_size) {
+  memcpy(reinterpret_cast<void*>(this), reinterpret_cast<const void*>(src),
+         ObjectSize(image_pointer_size));
+  declaring_class_ = GcRoot<mirror::Class>(const_cast<ArtMethod*>(src)->GetDeclaringClass());
+  dex_cache_resolved_methods_ = GcRoot<mirror::PointerArray>(
+      const_cast<ArtMethod*>(src)->GetDexCacheResolvedMethods());
+  dex_cache_resolved_types_ = GcRoot<mirror::ObjectArray<mirror::Class>>(
+      const_cast<ArtMethod*>(src)->GetDexCacheResolvedTypes());
+}
+
 }  // namespace art
 
-#endif  // ART_RUNTIME_MIRROR_ART_METHOD_INL_H_
+#endif  // ART_RUNTIME_ART_METHOD_INL_H_
diff --git a/runtime/mirror/art_method.cc b/runtime/art_method.cc
similarity index 88%
rename from runtime/mirror/art_method.cc
rename to runtime/art_method.cc
index 079a231..349013c 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/art_method.cc
@@ -16,12 +16,10 @@
 
 #include "art_method.h"
 
-#include "abstract_method.h"
 #include "arch/context.h"
 #include "art_field-inl.h"
 #include "art_method-inl.h"
 #include "base/stringpiece.h"
-#include "class-inl.h"
 #include "dex_file-inl.h"
 #include "dex_instruction.h"
 #include "entrypoints/entrypoint_utils.h"
@@ -32,15 +30,15 @@
 #include "jit/jit_code_cache.h"
 #include "jni_internal.h"
 #include "mapping_table.h"
-#include "object_array-inl.h"
-#include "object_array.h"
-#include "object-inl.h"
+#include "mirror/abstract_method.h"
+#include "mirror/class-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/object-inl.h"
+#include "mirror/string.h"
 #include "scoped_thread_state_change.h"
-#include "string.h"
 #include "well_known_classes.h"
 
 namespace art {
-namespace mirror {
 
 extern "C" void art_quick_invoke_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*,
                                       const char*);
@@ -49,9 +47,6 @@
                                              const char*);
 #endif
 
-// TODO: get global references for these
-GcRoot<Class> ArtMethod::java_lang_reflect_ArtMethod_;
-
 ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
                                           jobject jlr_method) {
   auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(jlr_method);
@@ -59,17 +54,13 @@
   return abstract_method->GetArtMethod();
 }
 
-void ArtMethod::VisitRoots(RootVisitor* visitor) {
-  java_lang_reflect_ArtMethod_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
 mirror::String* ArtMethod::GetNameAsString(Thread* self) {
-  mirror::ArtMethod* method = GetInterfaceMethodIfProxy();
-  const DexFile* dex_file = method->GetDexFile();
-  uint32_t dex_method_idx = method->GetDexMethodIndex();
-  const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
+  CHECK(!IsProxyMethod());
   StackHandleScope<1> hs(self);
-  Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
+  Handle<mirror::DexCache> dex_cache(hs.NewHandle(GetDexCache()));
+  auto* dex_file = dex_cache->GetDexFile();
+  uint32_t dex_method_idx = GetDexMethodIndex();
+  const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
   return Runtime::Current()->GetClassLinker()->ResolveString(*dex_file, method_id.name_idx_,
                                                              dex_cache);
 }
@@ -87,17 +78,6 @@
   }
 }
 
-void ArtMethod::SetClass(Class* java_lang_reflect_ArtMethod) {
-  CHECK(java_lang_reflect_ArtMethod_.IsNull());
-  CHECK(java_lang_reflect_ArtMethod != nullptr);
-  java_lang_reflect_ArtMethod_ = GcRoot<Class>(java_lang_reflect_ArtMethod);
-}
-
-void ArtMethod::ResetClass() {
-  CHECK(!java_lang_reflect_ArtMethod_.IsNull());
-  java_lang_reflect_ArtMethod_ = GcRoot<Class>(nullptr);
-}
-
 size_t ArtMethod::NumArgRegisters(const StringPiece& shorty) {
   CHECK_LE(1U, shorty.length());
   uint32_t num_registers = 0;
@@ -129,31 +109,33 @@
   return dex_file->GetMethodSignature(mid) == dex_file2->GetMethodSignature(mid2);
 }
 
-ArtMethod* ArtMethod::FindOverriddenMethod() {
+ArtMethod* ArtMethod::FindOverriddenMethod(size_t pointer_size) {
   if (IsStatic()) {
     return nullptr;
   }
-  Class* declaring_class = GetDeclaringClass();
-  Class* super_class = declaring_class->GetSuperClass();
+  mirror::Class* declaring_class = GetDeclaringClass();
+  mirror::Class* super_class = declaring_class->GetSuperClass();
   uint16_t method_index = GetMethodIndex();
   ArtMethod* result = nullptr;
   // Did this method override a super class method? If so load the result from the super class'
   // vtable
   if (super_class->HasVTable() && method_index < super_class->GetVTableLength()) {
-    result = super_class->GetVTableEntry(method_index);
+    result = super_class->GetVTableEntry(method_index, pointer_size);
   } else {
     // Method didn't override superclass method so search interfaces
     if (IsProxyMethod()) {
-      result = GetDexCacheResolvedMethods()->Get(GetDexMethodIndex());
+      result = GetDexCacheResolvedMethods()->GetElementPtrSize<ArtMethod*>(
+          GetDexMethodIndex(), pointer_size);
       CHECK_EQ(result,
                Runtime::Current()->GetClassLinker()->FindMethodForProxy(GetDeclaringClass(), this));
     } else {
-      IfTable* iftable = GetDeclaringClass()->GetIfTable();
+      mirror::IfTable* iftable = GetDeclaringClass()->GetIfTable();
       for (size_t i = 0; i < iftable->Count() && result == nullptr; i++) {
-        Class* interface = iftable->GetInterface(i);
+        mirror::Class* interface = iftable->GetInterface(i);
         for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
-          mirror::ArtMethod* interface_method = interface->GetVirtualMethod(j);
-          if (HasSameNameAndSignature(this, interface_method)) {
+          ArtMethod* interface_method = interface->GetVirtualMethod(j, pointer_size);
+          if (HasSameNameAndSignature(
+              this, interface_method->GetInterfaceMethodIfProxy(sizeof(void*)))) {
             result = interface_method;
             break;
           }
@@ -161,9 +143,8 @@
       }
     }
   }
-  if (kIsDebugBuild) {
-    DCHECK(result == nullptr || HasSameNameAndSignature(this, result));
-  }
+  DCHECK(result == nullptr || HasSameNameAndSignature(
+      GetInterfaceMethodIfProxy(sizeof(void*)), result->GetInterfaceMethodIfProxy(sizeof(void*))));
   return result;
 }
 
@@ -267,9 +248,9 @@
   return UINTPTR_MAX;
 }
 
-uint32_t ArtMethod::FindCatchBlock(Handle<ArtMethod> h_this, Handle<Class> exception_type,
+uint32_t ArtMethod::FindCatchBlock(Handle<mirror::Class> exception_type,
                                    uint32_t dex_pc, bool* has_no_move_exception) {
-  const DexFile::CodeItem* code_item = h_this->GetCodeItem();
+  const DexFile::CodeItem* code_item = GetCodeItem();
   // Set aside the exception while we resolve its type.
   Thread* self = Thread::Current();
   StackHandleScope<1> hs(self);
@@ -286,7 +267,7 @@
       break;
     }
     // Does this catch exception type apply?
-    Class* iter_exception_type = h_this->GetClassFromTypeIndex(iter_type_idx, true);
+    mirror::Class* iter_exception_type = GetClassFromTypeIndex(iter_type_idx, true);
     if (UNLIKELY(iter_exception_type == nullptr)) {
       // Now have a NoClassDefFoundError as exception. Ignore in case the exception class was
       // removed by a pro-guard like tool.
@@ -296,7 +277,7 @@
       // release its in use context at the end.
       delete self->GetLongJumpContext();
       LOG(WARNING) << "Unresolved exception class when finding catch block: "
-        << DescriptorToDot(h_this->GetTypeDescriptorFromTypeIdx(iter_type_idx));
+        << DescriptorToDot(GetTypeDescriptorFromTypeIdx(iter_type_idx));
     } else if (iter_exception_type->IsAssignableFrom(exception_type.Get())) {
       found_dex_pc = it.GetHandlerAddress();
       break;
@@ -378,7 +359,8 @@
 #ifndef NDEBUG
 uintptr_t ArtMethod::NativeQuickPcOffset(const uintptr_t pc, const void* quick_entry_point) {
   CHECK_NE(quick_entry_point, GetQuickToInterpreterBridge());
-  CHECK_EQ(quick_entry_point, Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this, sizeof(void*)));
+  CHECK_EQ(quick_entry_point,
+           Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this, sizeof(void*)));
   return pc - reinterpret_cast<uintptr_t>(quick_entry_point);
 }
 #endif
@@ -393,7 +375,7 @@
   if (kIsDebugBuild) {
     self->AssertThreadSuspensionIsAllowable();
     CHECK_EQ(kRunnable, self->GetState());
-    CHECK_STREQ(GetShorty(), shorty);
+    CHECK_STREQ(GetInterfaceMethodIfProxy(sizeof(void*))->GetShorty(), shorty);
   }
 
   // Push a transition back into managed code onto the linked list in thread.
@@ -408,16 +390,20 @@
     if (IsStatic()) {
       art::interpreter::EnterInterpreterFromInvoke(self, this, nullptr, args, result);
     } else {
-      Object* receiver = reinterpret_cast<StackReference<Object>*>(&args[0])->AsMirrorPtr();
+      mirror::Object* receiver =
+          reinterpret_cast<StackReference<mirror::Object>*>(&args[0])->AsMirrorPtr();
       art::interpreter::EnterInterpreterFromInvoke(self, this, receiver, args + 1, result);
     }
   } else {
-    const bool kLogInvocationStartAndReturn = false;
+    DCHECK_EQ(runtime->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
+
+    constexpr bool kLogInvocationStartAndReturn = false;
     bool have_quick_code = GetEntryPointFromQuickCompiledCode() != nullptr;
     if (LIKELY(have_quick_code)) {
       if (kLogInvocationStartAndReturn) {
-        LOG(INFO) << StringPrintf("Invoking '%s' quick code=%p", PrettyMethod(this).c_str(),
-                                  GetEntryPointFromQuickCompiledCode());
+        LOG(INFO) << StringPrintf(
+            "Invoking '%s' quick code=%p static=%d", PrettyMethod(this).c_str(),
+            GetEntryPointFromQuickCompiledCode(), static_cast<int>(IsStatic() ? 1 : 0));
       }
 
       // Ensure that we won't be accidentally calling quick compiled code when -Xint.
@@ -484,6 +470,11 @@
     return runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
   }
 
+  // This goes before IsProxyMethod since runtime methods have a null declaring class.
+  if (UNLIKELY(IsRuntimeMethod())) {
+    return runtime->GetRuntimeMethodFrameInfo(this);
+  }
+
   // For Proxy method we add special handling for the direct method case  (there is only one
   // direct method - constructor). Direct method is cloned from original
   // java.lang.reflect.Proxy class together with code and as a result it is executed as usual
@@ -500,10 +491,6 @@
     }
   }
 
-  if (UNLIKELY(IsRuntimeMethod())) {
-    return runtime->GetRuntimeMethodFrameInfo(this);
-  }
-
   const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(this, sizeof(void*));
   ClassLinker* class_linker = runtime->GetClassLinker();
   // On failure, instead of null we get the quick-generic-jni-trampoline for native method
@@ -519,11 +506,9 @@
     QuickMethodFrameInfo callee_info = runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
 
     // Callee saves + handle scope + method ref + alignment
-    size_t frame_size = RoundUp(callee_info.FrameSizeInBytes() + scope_size
-                                - sizeof(void*)  // callee-save frame stores a whole method pointer
-                                + sizeof(StackReference<mirror::ArtMethod>),
-                                kStackAlignment);
-
+    // Note: -sizeof(void*) since callee-save frame stores a whole method pointer.
+    size_t frame_size = RoundUp(callee_info.FrameSizeInBytes() - sizeof(void*) +
+                                sizeof(ArtMethod*) + scope_size, kStackAlignment);
     return QuickMethodFrameInfo(frame_size, callee_info.CoreSpillMask(), callee_info.FpSpillMask());
   }
 
@@ -573,5 +558,4 @@
   return true;
 }
 
-}  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/art_method.h b/runtime/art_method.h
similarity index 75%
rename from runtime/mirror/art_method.h
rename to runtime/art_method.h
index 0da5925..4a1e2c4 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/art_method.h
@@ -14,50 +14,61 @@
  * limitations under the License.
  */
 
-#ifndef ART_RUNTIME_MIRROR_ART_METHOD_H_
-#define ART_RUNTIME_MIRROR_ART_METHOD_H_
+#ifndef ART_RUNTIME_ART_METHOD_H_
+#define ART_RUNTIME_ART_METHOD_H_
 
 #include "dex_file.h"
 #include "gc_root.h"
 #include "invoke_type.h"
 #include "method_reference.h"
 #include "modifiers.h"
-#include "object.h"
+#include "mirror/object.h"
 #include "object_callbacks.h"
 #include "quick/quick_method_frame_info.h"
 #include "read_barrier_option.h"
 #include "stack.h"
 #include "stack_map.h"
+#include "utils.h"
 
 namespace art {
 
-struct ArtMethodOffsets;
-struct ConstructorMethodOffsets;
 union JValue;
 class ScopedObjectAccessAlreadyRunnable;
 class StringPiece;
 class ShadowFrame;
 
 namespace mirror {
+class Array;
+class Class;
+class PointerArray;
+}  // namespace mirror
 
 typedef void (EntryPointFromInterpreter)(Thread* self, const DexFile::CodeItem* code_item,
                                          ShadowFrame* shadow_frame, JValue* result);
 
-#define ART_METHOD_HAS_PADDING_FIELD_ON_64_BIT
-
-// C++ mirror of java.lang.reflect.ArtMethod.
-class MANAGED ArtMethod FINAL : public Object {
+class ArtMethod FINAL {
  public:
-  // Size of java.lang.reflect.ArtMethod.class.
-  static uint32_t ClassSize();
+  ArtMethod() : access_flags_(0), dex_code_item_offset_(0), dex_method_index_(0),
+      method_index_(0) { }
+
+  ArtMethod(const ArtMethod& src, size_t image_pointer_size) {
+    CopyFrom(&src, image_pointer_size);
+  }
 
   static ArtMethod* FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
                                         jobject jlr_method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Class* GetDeclaringClass() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE mirror::Class* GetDeclaringClassNoBarrier()
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  ALWAYS_INLINE mirror::Class* GetDeclaringClassUnchecked()
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void SetDeclaringClass(mirror::Class *new_declaring_class)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static MemberOffset DeclaringClassOffset() {
     return MemberOffset(OFFSETOF_MEMBER(ArtMethod, declaring_class_));
@@ -65,9 +76,9 @@
 
   ALWAYS_INLINE uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void SetAccessFlags(uint32_t new_access_flags) {
     // Not called within a transaction.
-    SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, access_flags_), new_access_flags);
+    access_flags_ = new_access_flags;
   }
 
   // Approximate what kind of method call would be used for this method.
@@ -180,7 +191,7 @@
 
   void SetMethodIndex(uint16_t new_method_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // Not called within a transaction.
-    SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_), new_method_index);
+    method_index_ = new_method_index;
   }
 
   static MemberOffset DexMethodIndexOffset() {
@@ -191,13 +202,13 @@
     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
   }
 
-  uint32_t GetCodeItemOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_code_item_offset_));
+  uint32_t GetCodeItemOffset() {
+    return dex_code_item_offset_;
   }
 
-  void SetCodeItemOffset(uint32_t new_code_off) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void SetCodeItemOffset(uint32_t new_code_off) {
     // Not called within a transaction.
-    SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_code_item_offset_), new_code_off);
+    dex_code_item_offset_ = new_code_off;
   }
 
   // Number of 32bit registers that would be required to hold all the arguments
@@ -205,9 +216,9 @@
 
   ALWAYS_INLINE uint32_t GetDexMethodIndex() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetDexMethodIndex(uint32_t new_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void SetDexMethodIndex(uint32_t new_idx) {
     // Not called within a transaction.
-    SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_), new_idx);
+    dex_method_index_ = new_idx;
   }
 
   static MemberOffset DexCacheResolvedMethodsOffset() {
@@ -218,26 +229,29 @@
     return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_);
   }
 
-  ALWAYS_INLINE ObjectArray<ArtMethod>* GetDexCacheResolvedMethods()
+  ALWAYS_INLINE mirror::PointerArray* GetDexCacheResolvedMethods()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  ALWAYS_INLINE ArtMethod* GetDexCacheResolvedMethod(uint16_t method_idx)
+  ALWAYS_INLINE ArtMethod* GetDexCacheResolvedMethod(uint16_t method_idx, size_t ptr_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  ALWAYS_INLINE void SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method)
+  ALWAYS_INLINE void SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method,
+                                               size_t ptr_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  ALWAYS_INLINE void SetDexCacheResolvedMethods(ObjectArray<ArtMethod>* new_dex_cache_methods)
+  ALWAYS_INLINE void SetDexCacheResolvedMethods(mirror::PointerArray* new_dex_cache_methods)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool HasDexCacheResolvedMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool HasSameDexCacheResolvedMethods(ArtMethod* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool HasSameDexCacheResolvedMethods(ObjectArray<ArtMethod>* other_cache)
+  bool HasSameDexCacheResolvedMethods(ArtMethod* other)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool HasSameDexCacheResolvedMethods(mirror::PointerArray* other_cache)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template <bool kWithCheck = true>
-  Class* GetDexCacheResolvedType(uint32_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types)
+  mirror::Class* GetDexCacheResolvedType(uint32_t type_idx)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetDexCacheResolvedTypes(mirror::ObjectArray<mirror::Class>* new_dex_cache_types)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool HasDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool HasSameDexCacheResolvedTypes(ArtMethod* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool HasSameDexCacheResolvedTypes(ObjectArray<Class>* other_cache)
+  bool HasSameDexCacheResolvedTypes(mirror::ObjectArray<mirror::Class>* other_cache)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get the Class* from the type index into this method's dex cache.
@@ -245,7 +259,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Find the method that this method overrides.
-  ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* FindOverriddenMethod(size_t pointer_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Find the method index for this method within other_dexfile. If this method isn't present then
   // return DexFile::kDexNoIndex. The name_and_signature_idx MUST refer to a MethodId with the same
@@ -258,59 +272,39 @@
   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_) {
-    CheckObjectSizeEqualsMirrorSize();
+  EntryPointFromInterpreter* GetEntryPointFromInterpreter() {
     return GetEntryPointFromInterpreterPtrSize(sizeof(void*));
   }
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  EntryPointFromInterpreter* GetEntryPointFromInterpreterPtrSize(size_t pointer_size)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetFieldPtrWithSize<EntryPointFromInterpreter*, kVerifyFlags>(
+  EntryPointFromInterpreter* GetEntryPointFromInterpreterPtrSize(size_t pointer_size) {
+    return GetEntryPoint<EntryPointFromInterpreter*>(
         EntryPointFromInterpreterOffset(pointer_size), pointer_size);
   }
 
-  template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  void SetEntryPointFromInterpreter(EntryPointFromInterpreter* entry_point_from_interpreter)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CheckObjectSizeEqualsMirrorSize();
+  void SetEntryPointFromInterpreter(EntryPointFromInterpreter* entry_point_from_interpreter) {
     SetEntryPointFromInterpreterPtrSize(entry_point_from_interpreter, sizeof(void*));
   }
-  template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetEntryPointFromInterpreterPtrSize(EntryPointFromInterpreter* entry_point_from_interpreter,
-                                           size_t pointer_size)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    SetFieldPtrWithSize<false, true, kVerifyFlags>(
-        EntryPointFromInterpreterOffset(pointer_size), entry_point_from_interpreter, pointer_size);
+                                           size_t pointer_size) {
+    SetEntryPoint(EntryPointFromInterpreterOffset(pointer_size), entry_point_from_interpreter,
+                  pointer_size);
   }
 
-  template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  const void* GetEntryPointFromQuickCompiledCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CheckObjectSizeEqualsMirrorSize();
+  const void* GetEntryPointFromQuickCompiledCode() {
     return GetEntryPointFromQuickCompiledCodePtrSize(sizeof(void*));
   }
-  template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ALWAYS_INLINE const void* GetEntryPointFromQuickCompiledCodePtrSize(size_t pointer_size)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetFieldPtrWithSize<const void*, kVerifyFlags>(
+  ALWAYS_INLINE const void* GetEntryPointFromQuickCompiledCodePtrSize(size_t pointer_size) {
+    return GetEntryPoint<const void*>(
         EntryPointFromQuickCompiledCodeOffset(pointer_size), pointer_size);
   }
 
-  template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CheckObjectSizeEqualsMirrorSize();
+  void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code) {
     SetEntryPointFromQuickCompiledCodePtrSize(entry_point_from_quick_compiled_code,
                                               sizeof(void*));
   }
-  template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ALWAYS_INLINE void SetEntryPointFromQuickCompiledCodePtrSize(
-      const void* entry_point_from_quick_compiled_code, size_t pointer_size)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    SetFieldPtrWithSize<false, true, kVerifyFlags>(
-        EntryPointFromQuickCompiledCodeOffset(pointer_size), entry_point_from_quick_compiled_code,
-        pointer_size);
+      const void* entry_point_from_quick_compiled_code, size_t pointer_size) {
+    SetEntryPoint(EntryPointFromQuickCompiledCodeOffset(pointer_size),
+                  entry_point_from_quick_compiled_code, pointer_size);
   }
 
   uint32_t GetCodeSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -318,7 +312,7 @@
   // Check whether the given PC is within the quick compiled code associated with this method's
   // quick entrypoint. This code isn't robust for instrumentation, etc. and is only used for
   // debug purposes.
-  bool PcIsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  bool PcIsWithinQuickCode(uintptr_t pc) {
     return PcIsWithinQuickCode(
         reinterpret_cast<uintptr_t>(GetEntryPointFromQuickCompiledCode()), pc);
   }
@@ -330,8 +324,8 @@
   // interpretered on invocation.
   bool IsEntrypointInterpreter() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  uint32_t GetQuickOatCodeOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void SetQuickOatCodeOffset(uint32_t code_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  uint32_t GetQuickOatCodeOffset();
+  void SetQuickOatCodeOffset(uint32_t code_offset);
 
   ALWAYS_INLINE static const void* EntryPointToCodePointer(const void* entry_point) {
     uintptr_t code = reinterpret_cast<uintptr_t>(entry_point);
@@ -394,7 +388,7 @@
   }
 
   FrameOffset GetHandleScopeOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    constexpr size_t handle_scope_offset = sizeof(StackReference<mirror::ArtMethod>);
+    constexpr size_t handle_scope_offset = sizeof(ArtMethod*);
     DCHECK_LT(handle_scope_offset, GetFrameSizeInBytes());
     return FrameOffset(handle_scope_offset);
   }
@@ -419,30 +413,23 @@
         PtrSizedFields, entry_point_from_quick_compiled_code_) / sizeof(void*) * pointer_size);
   }
 
-  void* GetEntryPointFromJni() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CheckObjectSizeEqualsMirrorSize();
+  void* GetEntryPointFromJni() {
     return GetEntryPointFromJniPtrSize(sizeof(void*));
   }
-  ALWAYS_INLINE void* GetEntryPointFromJniPtrSize(size_t pointer_size)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetFieldPtrWithSize<void*>(EntryPointFromJniOffset(pointer_size), pointer_size);
+  ALWAYS_INLINE void* GetEntryPointFromJniPtrSize(size_t pointer_size) {
+    return GetEntryPoint<void*>(EntryPointFromJniOffset(pointer_size), pointer_size);
   }
 
-  template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetEntryPointFromJni(const void* entrypoint) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CheckObjectSizeEqualsMirrorSize();
-    SetEntryPointFromJniPtrSize<kVerifyFlags>(entrypoint, sizeof(void*));
+    SetEntryPointFromJniPtrSize(entrypoint, sizeof(void*));
   }
-  template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ALWAYS_INLINE void SetEntryPointFromJniPtrSize(const void* entrypoint, size_t pointer_size)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    SetFieldPtrWithSize<false, true, kVerifyFlags>(
-        EntryPointFromJniOffset(pointer_size), entrypoint, pointer_size);
+  ALWAYS_INLINE void SetEntryPointFromJniPtrSize(const void* entrypoint, size_t pointer_size) {
+    SetEntryPoint(EntryPointFromJniOffset(pointer_size), entrypoint, pointer_size);
   }
 
   // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
   // conventions for a method of managed code. Returns false for Proxy methods.
-  bool IsRuntimeMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE bool IsRuntimeMethod();
 
   // Is this a hand crafted method used for something like describing callee saves?
   bool IsCalleeSaveMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -479,19 +466,12 @@
   // 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.
-  static uint32_t FindCatchBlock(Handle<ArtMethod> h_this, Handle<Class> exception_type,
-                                 uint32_t dex_pc, bool* has_no_move_exception)
+  uint32_t FindCatchBlock(Handle<mirror::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);
-
-  template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  static Class* GetJavaLangReflectArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  static void ResetClass();
-
-  static void VisitRoots(RootVisitor* visitor)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<typename RootVisitorType>
+  void VisitRoots(RootVisitorType& visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   const DexFile* GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -539,37 +519,35 @@
 
   mirror::DexCache* GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy(size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // May cause thread suspension due to class resolution.
   bool EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static size_t SizeWithoutPointerFields(size_t pointer_size) {
-    size_t total = sizeof(ArtMethod) - sizeof(PtrSizedFields);
-#ifdef ART_METHOD_HAS_PADDING_FIELD_ON_64_BIT
-    // Add 4 bytes if 64 bit, otherwise 0.
-    total += pointer_size - sizeof(uint32_t);
-#endif
-    return total;
-  }
-
-  // Size of an instance of java.lang.reflect.ArtMethod not including its value array.
-  static size_t InstanceSize(size_t pointer_size) {
-    return SizeWithoutPointerFields(pointer_size) +
+  // Size of an instance of this object.
+  static size_t ObjectSize(size_t pointer_size) {
+    return RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size) +
         (sizeof(PtrSizedFields) / sizeof(void*)) * pointer_size;
   }
 
+  void CopyFrom(const ArtMethod* src, size_t image_pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  ALWAYS_INLINE mirror::ObjectArray<mirror::Class>* GetDexCacheResolvedTypes()
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  protected:
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   // The class we are a part of.
-  HeapReference<Class> declaring_class_;
+  GcRoot<mirror::Class> declaring_class_;
 
   // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
-  HeapReference<ObjectArray<ArtMethod>> dex_cache_resolved_methods_;
+  GcRoot<mirror::PointerArray> dex_cache_resolved_methods_;
 
   // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access.
-  HeapReference<ObjectArray<Class>> dex_cache_resolved_types_;
+  GcRoot<mirror::ObjectArray<mirror::Class>> dex_cache_resolved_types_;
 
   // Access flags; low 16 bits are defined by spec.
   uint32_t access_flags_;
@@ -592,6 +570,8 @@
   // Fake padding field gets inserted here.
 
   // Must be the last fields in the method.
+  // PACKED(4) is necessary for the correctness of
+  // RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size).
   struct PACKED(4) PtrSizedFields {
     // Method dispatch from the interpreter invokes this pointer which may cause a bridge into
     // compiled code.
@@ -605,21 +585,36 @@
     void* entry_point_from_quick_compiled_code_;
   } ptr_sized_fields_;
 
-  static GcRoot<Class> java_lang_reflect_ArtMethod_;
-
  private:
-  ALWAYS_INLINE void CheckObjectSizeEqualsMirrorSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  ALWAYS_INLINE ObjectArray<Class>* GetDexCacheResolvedTypes()
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   static size_t PtrSizedFieldsOffset(size_t pointer_size) {
-    size_t offset = OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_);
-#ifdef ART_METHOD_HAS_PADDING_FIELD_ON_64_BIT
-    // Add 4 bytes if 64 bit, otherwise 0.
-    offset += pointer_size - sizeof(uint32_t);
-#endif
-    return offset;
+    // Round up to pointer size for padding field.
+    return RoundUp(OFFSETOF_MEMBER(ArtMethod, ptr_sized_fields_), pointer_size);
+  }
+
+  template<typename T>
+  ALWAYS_INLINE T GetEntryPoint(MemberOffset offset, size_t pointer_size) const {
+    DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
+    const auto addr = reinterpret_cast<uintptr_t>(this) + offset.Uint32Value();
+    if (pointer_size == sizeof(uint32_t)) {
+      return reinterpret_cast<T>(*reinterpret_cast<const uint32_t*>(addr));
+    } else {
+      auto v = *reinterpret_cast<const uint64_t*>(addr);
+      DCHECK_EQ(reinterpret_cast<uint64_t>(reinterpret_cast<T>(v)), v) << "Conversion lost bits";
+      return reinterpret_cast<T>(v);
+    }
+  }
+
+  template<typename T>
+  ALWAYS_INLINE void SetEntryPoint(MemberOffset offset, T new_value, size_t pointer_size) {
+    DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
+    const auto addr = reinterpret_cast<uintptr_t>(this) + offset.Uint32Value();
+    if (pointer_size == sizeof(uint32_t)) {
+      uintptr_t ptr = reinterpret_cast<uintptr_t>(new_value);
+      DCHECK_EQ(static_cast<uint32_t>(ptr), ptr) << "Conversion lost bits";
+      *reinterpret_cast<uint32_t*>(addr) = static_cast<uint32_t>(ptr);
+    } else {
+      *reinterpret_cast<uint64_t*>(addr) = reinterpret_cast<uintptr_t>(new_value);
+    }
   }
 
   // Code points to the start of the quick code.
@@ -640,11 +635,9 @@
         EntryPointToCodePointer(reinterpret_cast<const void*>(code)));
   }
 
-  friend struct art::ArtMethodOffsets;  // for verifying offset information
-  DISALLOW_IMPLICIT_CONSTRUCTORS(ArtMethod);
+  DISALLOW_COPY_AND_ASSIGN(ArtMethod);  // Need to use CopyFrom to deal with 32 vs 64 bits.
 };
 
-}  // namespace mirror
 }  // namespace art
 
-#endif  // ART_RUNTIME_MIRROR_ART_METHOD_H_
+#endif  // ART_RUNTIME_ART_METHOD_H_
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 3e677a4..d7efe1c 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -18,8 +18,8 @@
 #define ART_RUNTIME_ASM_SUPPORT_H_
 
 #if defined(__cplusplus)
+#include "art_method.h"
 #include "lock_word.h"
-#include "mirror/art_method.h"
 #include "mirror/class.h"
 #include "mirror/string.h"
 #include "runtime.h"
@@ -69,12 +69,12 @@
             art::Runtime::GetCalleeSaveMethodOffset(art::Runtime::kSaveAll))
 
 // Offset of field Runtime::callee_save_methods_[kRefsOnly]
-#define RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET COMPRESSED_REFERENCE_SIZE
+#define RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET 8
 ADD_TEST_EQ(static_cast<size_t>(RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET),
             art::Runtime::GetCalleeSaveMethodOffset(art::Runtime::kRefsOnly))
 
 // Offset of field Runtime::callee_save_methods_[kRefsAndArgs]
-#define RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET (2 * COMPRESSED_REFERENCE_SIZE)
+#define RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET (2 * 8)
 ADD_TEST_EQ(static_cast<size_t>(RUNTIME_REFS_AND_ARGS_CALLEE_SAVE_FRAME_OFFSET),
             art::Runtime::GetCalleeSaveMethodOffset(art::Runtime::kRefsAndArgs))
 
@@ -135,13 +135,13 @@
 #define MIRROR_CLASS_COMPONENT_TYPE_OFFSET (4 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_COMPONENT_TYPE_OFFSET,
             art::mirror::Class::ComponentTypeOffset().Int32Value())
-#define MIRROR_CLASS_ACCESS_FLAGS_OFFSET (44 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_ACCESS_FLAGS_OFFSET (36 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_ACCESS_FLAGS_OFFSET,
             art::mirror::Class::AccessFlagsOffset().Int32Value())
-#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (96 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (112 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_OBJECT_SIZE_OFFSET,
             art::mirror::Class::ObjectSizeOffset().Int32Value())
-#define MIRROR_CLASS_STATUS_OFFSET (108 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_STATUS_OFFSET (124 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_STATUS_OFFSET,
             art::mirror::Class::StatusOffset().Int32Value())
 
@@ -169,6 +169,10 @@
 ADD_TEST_EQ(static_cast<size_t>(MIRROR_OBJECT_ARRAY_COMPONENT_SIZE),
             sizeof(art::mirror::HeapReference<art::mirror::Object>))
 
+#define MIRROR_LONG_ARRAY_DATA_OFFSET (8 + MIRROR_OBJECT_HEADER_SIZE)
+ADD_TEST_EQ(MIRROR_LONG_ARRAY_DATA_OFFSET,
+            art::mirror::Array::DataOffset(sizeof(uint64_t)).Int32Value())
+
 // Offsets within java.lang.String.
 #define MIRROR_STRING_COUNT_OFFSET  MIRROR_OBJECT_HEADER_SIZE
 ADD_TEST_EQ(MIRROR_STRING_COUNT_OFFSET, art::mirror::String::CountOffset().Int32Value())
@@ -177,21 +181,21 @@
 ADD_TEST_EQ(MIRROR_STRING_VALUE_OFFSET, art::mirror::String::ValueOffset().Int32Value())
 
 // Offsets within java.lang.reflect.ArtMethod.
-#define MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET (4 + MIRROR_OBJECT_HEADER_SIZE)
-ADD_TEST_EQ(MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET,
-            art::mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value())
+#define ART_METHOD_DEX_CACHE_METHODS_OFFSET 4
+ADD_TEST_EQ(ART_METHOD_DEX_CACHE_METHODS_OFFSET,
+            art::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value())
 
-#define MIRROR_ART_METHOD_DEX_CACHE_TYPES_OFFSET (8 + MIRROR_OBJECT_HEADER_SIZE)
-ADD_TEST_EQ(MIRROR_ART_METHOD_DEX_CACHE_TYPES_OFFSET,
-            art::mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value())
+#define ART_METHOD_DEX_CACHE_TYPES_OFFSET 8
+ADD_TEST_EQ(ART_METHOD_DEX_CACHE_TYPES_OFFSET,
+            art::ArtMethod::DexCacheResolvedTypesOffset().Int32Value())
 
-#define MIRROR_ART_METHOD_QUICK_CODE_OFFSET_32        (36 + MIRROR_OBJECT_HEADER_SIZE)
-ADD_TEST_EQ(MIRROR_ART_METHOD_QUICK_CODE_OFFSET_32,
-            art::mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(4).Int32Value())
+#define ART_METHOD_QUICK_CODE_OFFSET_32 36
+ADD_TEST_EQ(ART_METHOD_QUICK_CODE_OFFSET_32,
+            art::ArtMethod::EntryPointFromQuickCompiledCodeOffset(4).Int32Value())
 
-#define MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64        (48 + MIRROR_OBJECT_HEADER_SIZE)
-ADD_TEST_EQ(MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64,
-            art::mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(8).Int32Value())
+#define ART_METHOD_QUICK_CODE_OFFSET_64 48
+ADD_TEST_EQ(ART_METHOD_QUICK_CODE_OFFSET_64,
+            art::ArtMethod::EntryPointFromQuickCompiledCodeOffset(8).Int32Value())
 
 #define LOCK_WORD_STATE_SHIFT 30
 ADD_TEST_EQ(LOCK_WORD_STATE_SHIFT, static_cast<int32_t>(art::LockWord::kStateShift))
diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc
index b53fa84..8f2d94b 100644
--- a/runtime/base/arena_allocator.cc
+++ b/runtime/base/arena_allocator.cc
@@ -302,6 +302,18 @@
   end_ = new_arena->End();
 }
 
+bool ArenaAllocator::Contains(const void* ptr) const {
+  if (ptr >= begin_ && ptr < end_) {
+    return true;
+  }
+  for (const Arena* cur_arena = arena_head_; cur_arena != nullptr; cur_arena = cur_arena->next_) {
+    if (cur_arena->Contains(ptr)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 MemStats::MemStats(const char* name, const ArenaAllocatorStats* stats, const Arena* first_arena,
                    ssize_t lost_bytes_adjustment)
     : name_(name),
diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h
index 2e617b5..d9723b5 100644
--- a/runtime/base/arena_allocator.h
+++ b/runtime/base/arena_allocator.h
@@ -142,6 +142,11 @@
     return bytes_allocated_;
   }
 
+  // Return true if ptr is contained in the arena.
+  bool Contains(const void* ptr) const {
+    return memory_ <= ptr && ptr < memory_ + bytes_allocated_;
+  }
+
  protected:
   size_t bytes_allocated_;
   uint8_t* memory_;
@@ -219,19 +224,52 @@
     return ret;
   }
 
+  // Realloc never frees the input pointer, it is the caller's job to do this if necessary.
+  void* Realloc(void* ptr, size_t ptr_size, size_t new_size,
+                ArenaAllocKind kind = kArenaAllocMisc) ALWAYS_INLINE {
+    DCHECK_GE(new_size, ptr_size);
+    DCHECK_EQ(ptr == nullptr, ptr_size == 0u);
+    auto* end = reinterpret_cast<uint8_t*>(ptr) + ptr_size;
+    // If we haven't allocated anything else, we can safely extend.
+    if (end == ptr_) {
+      const size_t size_delta = new_size - ptr_size;
+      // Check remain space.
+      const size_t remain = end_ - ptr_;
+      if (remain >= size_delta) {
+        ptr_ += size_delta;
+        ArenaAllocatorStats::RecordAlloc(size_delta, kind);
+        return ptr;
+      }
+    }
+    auto* new_ptr = Alloc(new_size, kind);
+    memcpy(new_ptr, ptr, ptr_size);
+    // TODO: Call free on ptr if linear alloc supports free.
+    return new_ptr;
+  }
+
   template <typename T>
   T* AllocArray(size_t length, ArenaAllocKind kind = kArenaAllocMisc) {
     return static_cast<T*>(Alloc(length * sizeof(T), kind));
   }
 
   void* AllocValgrind(size_t bytes, ArenaAllocKind kind);
+
   void ObtainNewArenaForAllocation(size_t allocation_size);
+
   size_t BytesAllocated() const;
+
   MemStats GetMemStats() const;
+
   // The BytesUsed method sums up bytes allocated from arenas in arena_head_ and nodes.
   // TODO: Change BytesAllocated to this behavior?
   size_t BytesUsed() const;
 
+  ArenaPool* GetArenaPool() const {
+    return pool_;
+  }
+
+  bool Contains(const void* ptr) const;
+
  private:
   static constexpr size_t kAlignment = 8;
 
diff --git a/runtime/base/iteration_range.h b/runtime/base/iteration_range.h
index 5a46376..6a0ef1f 100644
--- a/runtime/base/iteration_range.h
+++ b/runtime/base/iteration_range.h
@@ -17,6 +17,8 @@
 #ifndef ART_RUNTIME_BASE_ITERATION_RANGE_H_
 #define ART_RUNTIME_BASE_ITERATION_RANGE_H_
 
+#include <iterator>
+
 namespace art {
 
 // Helper class that acts as a container for range-based loops, given an iteration
@@ -38,10 +40,15 @@
   iterator cend() const { return last_; }
 
  private:
-  iterator first_;
-  iterator last_;
+  const iterator first_;
+  const iterator last_;
 };
 
+template <typename Iter>
+static inline IterationRange<Iter> MakeIterationRange(const Iter& begin_it, const Iter& end_it) {
+  return IterationRange<Iter>(begin_it, end_it);
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_BASE_ITERATION_RANGE_H_
diff --git a/runtime/base/macros.h b/runtime/base/macros.h
index c00ae78..5c59647 100644
--- a/runtime/base/macros.h
+++ b/runtime/base/macros.h
@@ -50,7 +50,6 @@
 #define ART_FRIEND_TYPED_TEST(test_set_name, individual_test)\
 template<typename T> ART_FRIEND_TEST(test_set_name, individual_test)
 
-
 // DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions. It goes in the private:
 // declarations in a class.
 #if !defined(DISALLOW_COPY_AND_ASSIGN)
diff --git a/runtime/base/scoped_arena_containers.h b/runtime/base/scoped_arena_containers.h
index df79085..82db60e 100644
--- a/runtime/base/scoped_arena_containers.h
+++ b/runtime/base/scoped_arena_containers.h
@@ -20,6 +20,7 @@
 #include <deque>
 #include <queue>
 #include <set>
+#include <unordered_map>
 #include <vector>
 
 #include "arena_containers.h"  // For ArenaAllocatorAdapterKind.
@@ -55,6 +56,11 @@
 using ScopedArenaSafeMap =
     SafeMap<K, V, Comparator, ScopedArenaAllocatorAdapter<std::pair<const K, V>>>;
 
+template <typename K, typename V, class Hash = std::hash<K>, class KeyEqual = std::equal_to<K>>
+using ScopedArenaUnorderedMap =
+    std::unordered_map<K, V, Hash, KeyEqual, ScopedArenaAllocatorAdapter<std::pair<const K, V>>>;
+
+
 // Implementation details below.
 
 template <>
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 30084d2..549eac2 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -20,6 +20,7 @@
 #include <zlib.h>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/to_str.h"
 #include "class_linker.h"
@@ -28,7 +29,6 @@
 #include "gc/space/space.h"
 #include "java_vm_ext.h"
 #include "jni_internal.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
@@ -200,7 +200,7 @@
   bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
                          jmethodID mid, Primitive::Type type, InvokeType invoke)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = CheckMethodID(soa, mid);
+    ArtMethod* m = CheckMethodID(soa, mid);
     if (m == nullptr) {
       return false;
     }
@@ -270,7 +270,7 @@
    */
   bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = CheckMethodID(soa, mid);
+    ArtMethod* m = CheckMethodID(soa, mid);
     if (m == nullptr) {
       return false;
     }
@@ -291,7 +291,7 @@
    */
   bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = CheckMethodID(soa, mid);
+    ArtMethod* m = CheckMethodID(soa, mid);
     if (m == nullptr) {
       return false;
     }
@@ -344,7 +344,7 @@
    */
   bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* traceMethod = nullptr;
+    ArtMethod* traceMethod = nullptr;
     if (has_method_ && soa.Vm()->IsTracingEnabled()) {
       // We need to guard some of the invocation interface's calls: a bad caller might
       // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
@@ -399,7 +399,7 @@
       Thread* self = Thread::Current();
       if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
         ScopedObjectAccess soa(self);
-        mirror::ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
+        ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
         should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
       }
     }
@@ -418,7 +418,7 @@
         if (has_method_) {
           Thread* self = Thread::Current();
           ScopedObjectAccess soa(self);
-          mirror::ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
+          ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
           std::string methodName(PrettyMethod(traceMethod, false));
           LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
           indent_ = methodName.size() + 1;
@@ -462,13 +462,13 @@
 
   bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* method = soa.DecodeMethod(mid);
+    ArtMethod* method = soa.DecodeMethod(mid);
     if (method == nullptr) {
       AbortF("expected non-null constructor");
       return false;
     }
     if (!method->IsConstructor() || method->IsStatic()) {
-      AbortF("expected a constructor but %s: %p", PrettyTypeOf(method).c_str(), mid);
+      AbortF("expected a constructor but %s: %p", PrettyMethod(method).c_str(), mid);
       return false;
     }
     return true;
@@ -825,7 +825,7 @@
       }
       case 'm': {  // jmethodID
         jmethodID mid = arg.m;
-        mirror::ArtMethod* m = soa.DecodeMethod(mid);
+        ArtMethod* m = soa.DecodeMethod(mid);
         *msg += PrettyMethod(m);
         if (!entry) {
           StringAppendF(msg, " (%p)", mid);
@@ -998,14 +998,15 @@
     return f;
   }
 
-  mirror::ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
+  ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (mid == nullptr) {
       AbortF("jmethodID was NULL");
       return nullptr;
     }
-    mirror::ArtMethod* m = soa.DecodeMethod(mid);
-    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) {
+    ArtMethod* m = soa.DecodeMethod(mid);
+    // TODO: Better check here.
+    if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
       Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
       AbortF("invalid jmethodID: %p", mid);
       return nullptr;
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index d87a563..d323379 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -17,8 +17,8 @@
 #ifndef ART_RUNTIME_CHECK_REFERENCE_MAP_VISITOR_H_
 #define ART_RUNTIME_CHECK_REFERENCE_MAP_VISITOR_H_
 
+#include "art_method-inl.h"
 #include "gc_map.h"
-#include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 #include "stack_map.h"
 
@@ -32,7 +32,7 @@
       : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     if (m->IsCalleeSaveMethod() || m->IsNative()) {
       CHECK_EQ(GetDexPc(), DexFile::kDexNoIndex);
     }
@@ -63,7 +63,7 @@
  private:
   void CheckOptimizedMethod(int* registers, int number_of_references, uint32_t native_pc_offset)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     CodeInfo code_info = m->GetOptimizedCodeInfo();
     StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
     uint16_t number_of_dex_registers = m->GetCodeItem()->registers_size_;
@@ -104,7 +104,7 @@
 
   void CheckQuickMethod(int* registers, int number_of_references, uint32_t native_pc_offset)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     NativePcOffsetToReferenceMap map(m->GetNativeGcMap(sizeof(void*)));
     const uint8_t* ref_bitmap = map.FindBitMap(native_pc_offset);
     CHECK(ref_bitmap);
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 1428749..df6703c 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -57,7 +57,7 @@
 }
 
 inline mirror::String* ClassLinker::ResolveString(uint32_t string_idx,
-                                                  mirror::ArtMethod* referrer) {
+                                                  ArtMethod* referrer) {
   mirror::Class* declaring_class = referrer->GetDeclaringClass();
   mirror::String* resolved_string = declaring_class->GetDexCacheStrings()->Get(string_idx);
   if (UNLIKELY(resolved_string == nullptr)) {
@@ -73,7 +73,7 @@
 }
 
 inline mirror::Class* ClassLinker::ResolveType(uint16_t type_idx,
-                                               mirror::ArtMethod* referrer) {
+                                               ArtMethod* referrer) {
   mirror::Class* resolved_type = referrer->GetDexCacheResolvedType(type_idx);
   if (UNLIKELY(resolved_type == nullptr)) {
     mirror::Class* declaring_class = referrer->GetDeclaringClass();
@@ -104,30 +104,27 @@
   return resolved_type;
 }
 
-inline mirror::ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx,
-                                                         mirror::ArtMethod* referrer) {
-  mirror::ArtMethod* resolved_method = referrer->GetDexCacheResolvedMethod(method_idx);
+inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer) {
+  ArtMethod* resolved_method = referrer->GetDexCacheResolvedMethod(
+      method_idx, image_pointer_size_);
   if (resolved_method == nullptr || resolved_method->IsRuntimeMethod()) {
     return nullptr;
   }
   return resolved_method;
 }
 
-inline mirror::ArtMethod* ClassLinker::ResolveMethod(Thread* self, uint32_t method_idx,
-                                                     mirror::ArtMethod** referrer,
-                                                     InvokeType type) {
-  mirror::ArtMethod* resolved_method = GetResolvedMethod(method_idx, *referrer);
-  if (LIKELY(resolved_method != nullptr)) {
-    return resolved_method;
+inline ArtMethod* ClassLinker::ResolveMethod(Thread* self, uint32_t method_idx,
+                                             ArtMethod* referrer, InvokeType type) {
+  ArtMethod* resolved_method = GetResolvedMethod(method_idx, referrer);
+  if (UNLIKELY(resolved_method == nullptr)) {
+    mirror::Class* declaring_class = referrer->GetDeclaringClass();
+    StackHandleScope<2> hs(self);
+    Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
+    Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
+    const DexFile* dex_file = h_dex_cache->GetDexFile();
+    resolved_method = ResolveMethod(*dex_file, method_idx, h_dex_cache, h_class_loader, referrer,
+                                    type);
   }
-  mirror::Class* declaring_class = (*referrer)->GetDeclaringClass();
-  StackHandleScope<3> hs(self);
-  Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
-  Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
-  HandleWrapper<mirror::ArtMethod> h_referrer(hs.NewHandleWrapper(referrer));
-  const DexFile* dex_file = h_dex_cache->GetDexFile();
-  resolved_method = ResolveMethod(*dex_file, method_idx, h_dex_cache, h_class_loader, h_referrer,
-                                  type);
   // Note: We cannot check here to see whether we added the method to the cache. It
   //       might be an erroneous class, which results in it being hidden from us.
   return resolved_method;
@@ -142,8 +139,8 @@
   return GetResolvedField(field_idx, field_declaring_class->GetDexCache());
 }
 
-inline ArtField* ClassLinker::ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer,
-                                                   bool is_static) {
+inline ArtField* ClassLinker::ResolveField(uint32_t field_idx, ArtMethod* referrer,
+                                           bool is_static) {
   mirror::Class* declaring_class = referrer->GetDeclaringClass();
   ArtField* resolved_field = GetResolvedField(field_idx, declaring_class);
   if (UNLIKELY(resolved_field == nullptr)) {
@@ -179,12 +176,6 @@
                                                     length);
 }
 
-inline mirror::ObjectArray<mirror::ArtMethod>* ClassLinker::AllocArtMethodArray(Thread* self,
-                                                                                size_t length) {
-  return mirror::ObjectArray<mirror::ArtMethod>::Alloc(self,
-      GetClassRoot(kJavaLangReflectArtMethodArrayClass), length);
-}
-
 inline mirror::IfTable* ClassLinker::AllocIfTable(Thread* self, size_t ifcount) {
   return down_cast<mirror::IfTable*>(
       mirror::IfTable::Alloc(self, GetClassRoot(kObjectArrayClass),
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 19bd96b..84da475 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -26,8 +26,11 @@
 #include <vector>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
+#include "base/arena_allocator.h"
 #include "base/casts.h"
 #include "base/logging.h"
+#include "base/scoped_arena_containers.h"
 #include "base/scoped_flock.h"
 #include "base/stl_util.h"
 #include "base/time_utils.h"
@@ -54,7 +57,6 @@
 #include "oat_file.h"
 #include "oat_file_assistant.h"
 #include "object_lock.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
@@ -94,9 +96,9 @@
   va_end(args);
 }
 
-static bool HasInitWithString(Thread* self, ClassLinker* class_linker, const char* descriptor)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ArtMethod* method = self->GetCurrentMethod(nullptr);
+bool ClassLinker::HasInitWithString(
+    Thread* self, ClassLinker* class_linker, const char* descriptor) {
+  ArtMethod* method = self->GetCurrentMethod(nullptr);
   StackHandleScope<1> hs(self);
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(method != nullptr ?
       method->GetDeclaringClass()->GetClassLoader()
@@ -110,8 +112,8 @@
     return false;
   }
 
-  mirror::ArtMethod* exception_init_method =
-      exception_class->FindDeclaredDirectMethod("<init>", "(Ljava/lang/String;)V");
+  ArtMethod* exception_init_method = exception_class->FindDeclaredDirectMethod(
+      "<init>", "(Ljava/lang/String;)V", image_pointer_size_);
   return exception_init_method != nullptr;
 }
 
@@ -275,46 +277,51 @@
       quick_to_interpreter_bridge_trampoline_(nullptr),
       image_pointer_size_(sizeof(void*)) {
   CHECK(intern_table_ != nullptr);
-  for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
-    find_array_class_cache_[i] = GcRoot<mirror::Class>(nullptr);
+  for (auto& root : find_array_class_cache_) {
+    root = GcRoot<mirror::Class>(nullptr);
   }
 }
 
 void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> boot_class_path) {
   VLOG(startup) << "ClassLinker::Init";
-  CHECK(!Runtime::Current()->GetHeap()->HasImageSpace()) << "Runtime has image. We should use it.";
 
+  Thread* const self = Thread::Current();
+  Runtime* const runtime = Runtime::Current();
+  gc::Heap* const heap = runtime->GetHeap();
+
+  CHECK(!heap->HasImageSpace()) << "Runtime has image. We should use it.";
   CHECK(!init_done_);
 
+  // Use the pointer size from the runtime since we are probably creating the image.
+  image_pointer_size_ = InstructionSetPointerSize(runtime->GetInstructionSet());
+
   // java_lang_Class comes first, it's needed for AllocClass
-  Thread* const self = Thread::Current();
-  gc::Heap* const heap = Runtime::Current()->GetHeap();
   // The GC can't handle an object with a null class since we can't get the size of this object.
   heap->IncrementDisableMovingGC(self);
   StackHandleScope<64> hs(self);  // 64 is picked arbitrarily.
+  auto class_class_size = mirror::Class::ClassClassSize(image_pointer_size_);
   Handle<mirror::Class> java_lang_Class(hs.NewHandle(down_cast<mirror::Class*>(
-      heap->AllocNonMovableObject<true>(self, nullptr,
-                                        mirror::Class::ClassClassSize(),
-                                        VoidFunctor()))));
+      heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor()))));
   CHECK(java_lang_Class.Get() != nullptr);
   mirror::Class::SetClassClass(java_lang_Class.Get());
   java_lang_Class->SetClass(java_lang_Class.Get());
   if (kUseBakerOrBrooksReadBarrier) {
     java_lang_Class->AssertReadBarrierPointer();
   }
-  java_lang_Class->SetClassSize(mirror::Class::ClassClassSize());
+  java_lang_Class->SetClassSize(class_class_size);
   java_lang_Class->SetPrimitiveType(Primitive::kPrimNot);
   heap->DecrementDisableMovingGC(self);
   // AllocClass(mirror::Class*) can now be used
 
   // Class[] is used for reflection support.
+  auto class_array_class_size = mirror::ObjectArray<mirror::Class>::ClassSize(image_pointer_size_);
   Handle<mirror::Class> class_array_class(hs.NewHandle(
-     AllocClass(self, java_lang_Class.Get(), mirror::ObjectArray<mirror::Class>::ClassSize())));
+      AllocClass(self, java_lang_Class.Get(), class_array_class_size)));
   class_array_class->SetComponentType(java_lang_Class.Get());
 
   // java_lang_Object comes next so that object_array_class can be created.
   Handle<mirror::Class> java_lang_Object(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(), mirror::Object::ClassSize())));
+      AllocClass(self, java_lang_Class.Get(), mirror::Object::ClassSize(image_pointer_size_))));
   CHECK(java_lang_Object.Get() != nullptr);
   // backfill Object as the super class of Class.
   java_lang_Class->SetSuperClass(java_lang_Object.Get());
@@ -322,12 +329,14 @@
 
   // Object[] next to hold class roots.
   Handle<mirror::Class> object_array_class(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(), mirror::ObjectArray<mirror::Object>::ClassSize())));
+      AllocClass(self, java_lang_Class.Get(),
+                 mirror::ObjectArray<mirror::Object>::ClassSize(image_pointer_size_))));
   object_array_class->SetComponentType(java_lang_Object.Get());
 
   // Setup the char (primitive) class to be used for char[].
   Handle<mirror::Class> char_class(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(), mirror::Class::PrimitiveClassSize())));
+      AllocClass(self, java_lang_Class.Get(),
+                 mirror::Class::PrimitiveClassSize(image_pointer_size_))));
   // The primitive char class won't be initialized by
   // InitializePrimitiveClass until line 459, but strings (and
   // internal char arrays) will be allocated before that and the
@@ -337,21 +346,20 @@
 
   // Setup the char[] class to be used for String.
   Handle<mirror::Class> char_array_class(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(),
-                 mirror::Array::ClassSize())));
+      AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
   char_array_class->SetComponentType(char_class.Get());
   mirror::CharArray::SetArrayClass(char_array_class.Get());
 
   // Setup String.
   Handle<mirror::Class> java_lang_String(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(), mirror::String::ClassSize())));
+      AllocClass(self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_))));
   mirror::String::SetClass(java_lang_String.Get());
   mirror::Class::SetStatus(java_lang_String, mirror::Class::kStatusResolved, self);
   java_lang_String->SetStringClass();
 
   // Setup java.lang.ref.Reference.
   Handle<mirror::Class> java_lang_ref_Reference(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(), mirror::Reference::ClassSize())));
+      AllocClass(self, java_lang_Class.Get(), mirror::Reference::ClassSize(image_pointer_size_))));
   mirror::Reference::SetClass(java_lang_ref_Reference.Get());
   java_lang_ref_Reference->SetObjectSize(mirror::Reference::InstanceSize());
   mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusResolved, self);
@@ -384,14 +392,14 @@
 
   // Create int array type for AllocDexCache (done in AppendToBootClassPath).
   Handle<mirror::Class> int_array_class(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize())));
+      AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
   int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
   mirror::IntArray::SetArrayClass(int_array_class.Get());
   SetClassRoot(kIntArrayClass, int_array_class.Get());
 
   // Create long array type for AllocDexCache (done in AppendToBootClassPath).
   Handle<mirror::Class> long_array_class(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize())));
+      AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_))));
   long_array_class->SetComponentType(GetClassRoot(kPrimitiveLong));
   mirror::LongArray::SetArrayClass(long_array_class.Get());
   SetClassRoot(kLongArrayClass, long_array_class.Get());
@@ -400,35 +408,22 @@
 
   // Set up DexCache. This cannot be done later since AppendToBootClassPath calls AllocDexCache.
   Handle<mirror::Class> java_lang_DexCache(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(), mirror::DexCache::ClassSize())));
+      AllocClass(self, java_lang_Class.Get(), mirror::DexCache::ClassSize(image_pointer_size_))));
   SetClassRoot(kJavaLangDexCache, java_lang_DexCache.Get());
   java_lang_DexCache->SetObjectSize(mirror::DexCache::InstanceSize());
   mirror::Class::SetStatus(java_lang_DexCache, mirror::Class::kStatusResolved, self);
 
-  // Constructor, Method, and AbstractMethod are necessary so
-  // that FindClass can link members.
-
-  Handle<mirror::Class> java_lang_reflect_ArtMethod(hs.NewHandle(
-    AllocClass(self, java_lang_Class.Get(), mirror::ArtMethod::ClassSize())));
-  CHECK(java_lang_reflect_ArtMethod.Get() != nullptr);
-  size_t pointer_size = GetInstructionSetPointerSize(Runtime::Current()->GetInstructionSet());
-  java_lang_reflect_ArtMethod->SetObjectSize(mirror::ArtMethod::InstanceSize(pointer_size));
-  SetClassRoot(kJavaLangReflectArtMethod, java_lang_reflect_ArtMethod.Get());
-  mirror::Class::SetStatus(java_lang_reflect_ArtMethod, mirror::Class::kStatusResolved, self);
-  mirror::ArtMethod::SetClass(java_lang_reflect_ArtMethod.Get());
-
   // Set up array classes for string, field, method
   Handle<mirror::Class> object_array_string(hs.NewHandle(
       AllocClass(self, java_lang_Class.Get(),
-                 mirror::ObjectArray<mirror::String>::ClassSize())));
+                 mirror::ObjectArray<mirror::String>::ClassSize(image_pointer_size_))));
   object_array_string->SetComponentType(java_lang_String.Get());
   SetClassRoot(kJavaLangStringArrayClass, object_array_string.Get());
 
-  Handle<mirror::Class> object_array_art_method(hs.NewHandle(
-      AllocClass(self, java_lang_Class.Get(),
-                 mirror::ObjectArray<mirror::ArtMethod>::ClassSize())));
-  object_array_art_method->SetComponentType(java_lang_reflect_ArtMethod.Get());
-  SetClassRoot(kJavaLangReflectArtMethodArrayClass, object_array_art_method.Get());
+  // Create runtime resolution and imt conflict methods.
+  runtime->SetResolutionMethod(runtime->CreateResolutionMethod());
+  runtime->SetImtConflictMethod(runtime->CreateImtConflictMethod());
+  runtime->SetImtUnimplementedMethod(runtime->CreateImtConflictMethod());
 
   // Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create
   // DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses
@@ -446,13 +441,6 @@
   InitializePrimitiveClass(char_class.Get(), Primitive::kPrimChar);
   SetClassRoot(kPrimitiveChar, char_class.Get());  // needs descriptor
 
-  // Create runtime resolution and imt conflict methods. Also setup the default imt.
-  Runtime* runtime = Runtime::Current();
-  runtime->SetResolutionMethod(runtime->CreateResolutionMethod());
-  runtime->SetImtConflictMethod(runtime->CreateImtConflictMethod());
-  runtime->SetImtUnimplementedMethod(runtime->CreateImtConflictMethod());
-  runtime->SetDefaultImt(runtime->CreateDefaultImt(this));
-
   // Set up GenericJNI entrypoint. That is mainly a hack for common_compiler_test.h so that
   // we do not need friend classes or a publicly exposed setter.
   quick_generic_jni_trampoline_ = GetQuickGenericJniStub();
@@ -529,13 +517,8 @@
   // dex_cache_ fields and register them in class_table_.
   CHECK_EQ(java_lang_Class.Get(), FindSystemClass(self, "Ljava/lang/Class;"));
 
-  mirror::Class::SetStatus(java_lang_reflect_ArtMethod, mirror::Class::kStatusNotReady, self);
-  CHECK_EQ(java_lang_reflect_ArtMethod.Get(),
-           FindSystemClass(self, "Ljava/lang/reflect/ArtMethod;"));
   CHECK_EQ(object_array_string.Get(),
            FindSystemClass(self, GetClassRootDescriptor(kJavaLangStringArrayClass)));
-  CHECK_EQ(object_array_art_method.Get(),
-           FindSystemClass(self, GetClassRootDescriptor(kJavaLangReflectArtMethodArrayClass)));
 
   // End of special init trickery, subsequent classes may be loaded via FindSystemClass.
 
@@ -579,7 +562,8 @@
   mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusNotReady, self);
   CHECK_EQ(java_lang_ref_Reference.Get(), FindSystemClass(self, "Ljava/lang/ref/Reference;"));
   CHECK_EQ(java_lang_ref_Reference->GetObjectSize(), mirror::Reference::InstanceSize());
-  CHECK_EQ(java_lang_ref_Reference->GetClassSize(), mirror::Reference::ClassSize());
+  CHECK_EQ(java_lang_ref_Reference->GetClassSize(),
+           mirror::Reference::ClassSize(image_pointer_size_));
   class_root = FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;");
   class_root->SetAccessFlags(class_root->GetAccessFlags() |
                              kAccClassIsReference | kAccClassIsFinalizerReference);
@@ -1027,24 +1011,41 @@
   return nullptr;
 }
 
-void ClassLinker::InitFromImageInterpretOnlyCallback(mirror::Object* obj, void* arg) {
-  ClassLinker* class_linker = reinterpret_cast<ClassLinker*>(arg);
-  DCHECK(obj != nullptr);
-  DCHECK(class_linker != nullptr);
-  if (obj->IsArtMethod()) {
-    mirror::ArtMethod* method = obj->AsArtMethod();
-    if (!method->IsNative()) {
-      const size_t pointer_size = class_linker->image_pointer_size_;
-      method->SetEntryPointFromInterpreterPtrSize(artInterpreterToInterpreterBridge, pointer_size);
-      if (!method->IsRuntimeMethod() && method != Runtime::Current()->GetResolutionMethod()) {
-        method->SetEntryPointFromQuickCompiledCodePtrSize(GetQuickToInterpreterBridge(),
-                                                          pointer_size);
-      }
+static void SanityCheckArtMethod(ArtMethod* m, mirror::Class* expected_class,
+                                 gc::space::ImageSpace* space)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  if (m->IsRuntimeMethod()) {
+    CHECK(m->GetDeclaringClass() == nullptr) << PrettyMethod(m);
+  } else if (m->IsMiranda()) {
+    CHECK(m->GetDeclaringClass() != nullptr) << PrettyMethod(m);
+  } else if (expected_class != nullptr) {
+    CHECK_EQ(m->GetDeclaringClassUnchecked(), expected_class) << PrettyMethod(m);
+  }
+  if (space != nullptr) {
+    auto& header = space->GetImageHeader();
+    auto& methods = header.GetMethodsSection();
+    auto offset = reinterpret_cast<uint8_t*>(m) - space->Begin();
+    CHECK(methods.Contains(offset)) << m << " not in " << methods;
+  }
+}
+
+static void SanityCheckArtMethodPointerArray(
+    mirror::PointerArray* arr, mirror::Class* expected_class, size_t pointer_size,
+    gc::space::ImageSpace* space) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  CHECK(arr != nullptr);
+  for (int32_t j = 0; j < arr->GetLength(); ++j) {
+    auto* method = arr->GetElementPtrSize<ArtMethod*>(j, pointer_size);
+    // expected_class == null means we are a dex cache.
+    if (expected_class != nullptr) {
+      CHECK(method != nullptr);
+    }
+    if (method != nullptr) {
+      SanityCheckArtMethod(method, expected_class, space);
     }
   }
 }
 
-void SanityCheckObjectsCallback(mirror::Object* obj, void* arg ATTRIBUTE_UNUSED)
+static void SanityCheckObjectsCallback(mirror::Object* obj, void* arg ATTRIBUTE_UNUSED)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(obj != nullptr);
   CHECK(obj->GetClass() != nullptr) << "Null class " << obj;
@@ -1058,6 +1059,36 @@
         CHECK_EQ(fields[i][j].GetDeclaringClass(), klass);
       }
     }
+    auto* runtime = Runtime::Current();
+    auto* image_space = runtime->GetHeap()->GetImageSpace();
+    auto pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
+    for (auto& m : klass->GetDirectMethods(pointer_size)) {
+      SanityCheckArtMethod(&m, klass, image_space);
+    }
+    for (auto& m : klass->GetVirtualMethods(pointer_size)) {
+      SanityCheckArtMethod(&m, klass, image_space);
+    }
+    auto* vtable = klass->GetVTable();
+    if (vtable != nullptr) {
+      SanityCheckArtMethodPointerArray(vtable, nullptr, pointer_size, image_space);
+    }
+    if (klass->ShouldHaveEmbeddedImtAndVTable()) {
+      for (size_t i = 0; i < mirror::Class::kImtSize; ++i) {
+        SanityCheckArtMethod(klass->GetEmbeddedImTableEntry(i, pointer_size), nullptr, image_space);
+      }
+      for (int32_t i = 0; i < klass->GetEmbeddedVTableLength(); ++i) {
+        SanityCheckArtMethod(klass->GetEmbeddedVTableEntry(i, pointer_size), nullptr, image_space);
+      }
+    }
+    auto* iftable = klass->GetIfTable();
+    if (iftable != nullptr) {
+      for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
+        if (iftable->GetMethodArrayCount(i) > 0) {
+          SanityCheckArtMethodPointerArray(iftable->GetMethodArray(i), nullptr, pointer_size,
+                                           image_space);
+        }
+      }
+    }
   }
 }
 
@@ -1069,8 +1100,9 @@
   Thread* const self = Thread::Current();
   gc::Heap* const heap = runtime->GetHeap();
   gc::space::ImageSpace* const space = heap->GetImageSpace();
-  dex_cache_image_class_lookup_required_ = true;
   CHECK(space != nullptr);
+  image_pointer_size_ = space->GetImageHeader().GetPointerSize();
+  dex_cache_image_class_lookup_required_ = true;
   OatFile& oat_file = GetImageOatFile(space);
   CHECK_EQ(oat_file.GetOatHeader().GetImageFileLocationOatChecksum(), 0U);
   CHECK_EQ(oat_file.GetOatHeader().GetImageFileLocationOatDataBegin(), 0U);
@@ -1113,34 +1145,28 @@
       UNREACHABLE();
     }
 
+    if (kSanityCheckObjects) {
+      SanityCheckArtMethodPointerArray(dex_cache->GetResolvedMethods(), nullptr,
+                                       image_pointer_size_, space);
+    }
+
     CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
 
     AppendToBootClassPath(*dex_file.get(), dex_cache);
     opened_dex_files_.push_back(std::move(dex_file));
   }
 
+  CHECK(ValidPointerSize(image_pointer_size_)) << image_pointer_size_;
+
   // Set classes on AbstractMethod early so that IsMethod tests can be performed during the live
   // bitmap walk.
-  mirror::ArtMethod::SetClass(GetClassRoot(kJavaLangReflectArtMethod));
-  size_t art_method_object_size = mirror::ArtMethod::GetJavaLangReflectArtMethod()->GetObjectSize();
   if (!runtime->IsAotCompiler()) {
-    // Aot compiler supports having an image with a different pointer size than the runtime. This
-    // happens on the host for compile 32 bit tests since we use a 64 bit libart compiler. We may
-    // also use 32 bit dex2oat on a system with 64 bit apps.
-    CHECK_EQ(art_method_object_size, mirror::ArtMethod::InstanceSize(sizeof(void*)))
-        << sizeof(void*);
-  }
-  if (art_method_object_size == mirror::ArtMethod::InstanceSize(4)) {
-    image_pointer_size_ = 4;
-  } else {
-    CHECK_EQ(art_method_object_size, mirror::ArtMethod::InstanceSize(8));
-    image_pointer_size_ = 8;
+    // Only the Aot compiler supports having an image with a different pointer size than the
+    // runtime. This happens on the host for compile 32 bit tests since we use a 64 bit libart
+    // compiler. We may also use 32 bit dex2oat on a system with 64 bit apps.
+    CHECK_EQ(image_pointer_size_, sizeof(void*));
   }
 
-  // Set entry point to interpreter if in InterpretOnly mode.
-  if (!runtime->IsAotCompiler() && runtime->GetInstrumentation()->InterpretOnly()) {
-    heap->VisitObjects(InitFromImageInterpretOnlyCallback, this);
-  }
   if (kSanityCheckObjects) {
     for (int32_t i = 0; i < dex_caches->GetLength(); i++) {
       auto* dex_cache = dex_caches->Get(i);
@@ -1154,6 +1180,27 @@
     heap->VisitObjects(SanityCheckObjectsCallback, nullptr);
   }
 
+  // Set entry point to interpreter if in InterpretOnly mode.
+  if (!runtime->IsAotCompiler() && runtime->GetInstrumentation()->InterpretOnly()) {
+    const auto& header = space->GetImageHeader();
+    const auto& methods = header.GetMethodsSection();
+    const auto art_method_size = ArtMethod::ObjectSize(image_pointer_size_);
+    for (uintptr_t pos = 0; pos < methods.Size(); pos += art_method_size) {
+      auto* method = reinterpret_cast<ArtMethod*>(space->Begin() + pos + methods.Offset());
+      if (kIsDebugBuild && !method->IsRuntimeMethod()) {
+        CHECK(method->GetDeclaringClass() != nullptr);
+      }
+      if (!method->IsNative()) {
+        method->SetEntryPointFromInterpreterPtrSize(
+            artInterpreterToInterpreterBridge, image_pointer_size_);
+        if (!method->IsRuntimeMethod() && method != runtime->GetResolutionMethod()) {
+          method->SetEntryPointFromQuickCompiledCodePtrSize(GetQuickToInterpreterBridge(),
+                                                            image_pointer_size_);
+        }
+      }
+    }
+  }
+
   // reinit class_roots_
   mirror::Class::SetClassClass(class_roots->Get(kJavaLangClass));
   class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(class_roots.Get());
@@ -1185,24 +1232,49 @@
   VLOG(startup) << "ClassLinker::InitFromImage exiting";
 }
 
+bool ClassLinker::ClassInClassTable(mirror::Class* klass) {
+  ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+  auto it = class_table_.Find(GcRoot<mirror::Class>(klass));
+  if (it == class_table_.end()) {
+    return false;
+  }
+  return it->Read() == klass;
+}
+
 void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) {
   WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
   BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(
       visitor, RootInfo(kRootStickyClass));
   if ((flags & kVisitRootFlagAllRoots) != 0) {
+    // Argument for how root visiting deals with ArtField and ArtMethod roots.
+    // There is 3 GC cases to handle:
+    // Non moving concurrent:
+    // This case is easy to handle since the reference members of ArtMethod and ArtFields are held
+    // live by the class and class roots. In this case we probably don't even need to call
+    // VisitNativeRoots.
+    //
+    // Moving non-concurrent:
+    // This case needs to call visit VisitNativeRoots in case the classes or dex cache arrays move.
+    // To prevent missing roots, this case needs to ensure that there is no
+    // suspend points between the point which we allocate ArtMethod arrays and place them in a
+    // class which is in the class table.
+    //
+    // Moving concurrent:
+    // Need to make sure to not copy ArtMethods without doing read barriers since the roots are
+    // marked concurrently and we don't hold the classlinker_classes_lock_ when we do the copy.
     for (GcRoot<mirror::Class>& root : class_table_) {
       buffered_visitor.VisitRoot(root);
-      root.Read()->VisitFieldRoots(buffered_visitor);
+      root.Read()->VisitNativeRoots(buffered_visitor, image_pointer_size_);
     }
     // PreZygote classes can't move so we won't need to update fields' declaring classes.
     for (GcRoot<mirror::Class>& root : pre_zygote_class_table_) {
       buffered_visitor.VisitRoot(root);
-      root.Read()->VisitFieldRoots(buffered_visitor);
+      root.Read()->VisitNativeRoots(buffered_visitor, image_pointer_size_);
     }
   } else if ((flags & kVisitRootFlagNewRoots) != 0) {
     for (auto& root : new_class_roots_) {
       mirror::Class* old_ref = root.Read<kWithoutReadBarrier>();
-      old_ref->VisitFieldRoots(buffered_visitor);
+      old_ref->VisitNativeRoots(buffered_visitor, image_pointer_size_);
       root.VisitRoot(visitor, RootInfo(kRootStickyClass));
       mirror::Class* new_ref = root.Read<kWithoutReadBarrier>();
       if (UNLIKELY(new_ref != old_ref)) {
@@ -1353,7 +1425,6 @@
 }
 
 ClassLinker::~ClassLinker() {
-  mirror::ArtMethod::ResetClass();
   mirror::Class::ResetClass();
   mirror::Constructor::ResetClass();
   mirror::Field::ResetClass();
@@ -1376,49 +1447,47 @@
   STLDeleteElements(&oat_files_);
 }
 
+mirror::PointerArray* ClassLinker::AllocPointerArray(Thread* self, size_t length) {
+  return down_cast<mirror::PointerArray*>(image_pointer_size_ == 8u ?
+      static_cast<mirror::Array*>(mirror::LongArray::Alloc(self, length)) :
+      static_cast<mirror::Array*>(mirror::IntArray::Alloc(self, length)));
+}
+
 mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) {
-  gc::Heap* const heap = Runtime::Current()->GetHeap();
-  StackHandleScope<16> hs(self);
-  Handle<mirror::Class> dex_cache_class(hs.NewHandle(GetClassRoot(kJavaLangDexCache)));
-  Handle<mirror::DexCache> dex_cache(
-      hs.NewHandle(down_cast<mirror::DexCache*>(
-          heap->AllocObject<true>(self, dex_cache_class.Get(), dex_cache_class->GetObjectSize(),
-                                  VoidFunctor()))));
+  StackHandleScope<6> hs(self);
+  auto dex_cache(hs.NewHandle(down_cast<mirror::DexCache*>(
+      GetClassRoot(kJavaLangDexCache)->AllocObject(self))));
   if (dex_cache.Get() == nullptr) {
+    self->AssertPendingOOMException();
     return nullptr;
   }
-  Handle<mirror::String>
-      location(hs.NewHandle(intern_table_->InternStrong(dex_file.GetLocation().c_str())));
+  auto location(hs.NewHandle(intern_table_->InternStrong(dex_file.GetLocation().c_str())));
   if (location.Get() == nullptr) {
+    self->AssertPendingOOMException();
     return nullptr;
   }
-  Handle<mirror::ObjectArray<mirror::String>>
-      strings(hs.NewHandle(AllocStringArray(self, dex_file.NumStringIds())));
+  auto strings(hs.NewHandle(AllocStringArray(self, dex_file.NumStringIds())));
   if (strings.Get() == nullptr) {
+    self->AssertPendingOOMException();
     return nullptr;
   }
-  Handle<mirror::ObjectArray<mirror::Class>>
-      types(hs.NewHandle(AllocClassArray(self, dex_file.NumTypeIds())));
+  auto types(hs.NewHandle(AllocClassArray(self, dex_file.NumTypeIds())));
   if (types.Get() == nullptr) {
+    self->AssertPendingOOMException();
     return nullptr;
   }
-  Handle<mirror::ObjectArray<mirror::ArtMethod>>
-      methods(hs.NewHandle(AllocArtMethodArray(self, dex_file.NumMethodIds())));
+  auto methods(hs.NewHandle(AllocPointerArray(self, dex_file.NumMethodIds())));
   if (methods.Get() == nullptr) {
+    self->AssertPendingOOMException();
     return nullptr;
   }
-  Handle<mirror::Array> fields;
-  if (image_pointer_size_ == 8u) {
-    fields = hs.NewHandle<mirror::Array>(mirror::LongArray::Alloc(self, dex_file.NumFieldIds()));
-  } else {
-    DCHECK_EQ(image_pointer_size_, 4u);
-    fields = hs.NewHandle<mirror::Array>(mirror::IntArray::Alloc(self, dex_file.NumFieldIds()));
-  }
+  auto fields(hs.NewHandle(AllocPointerArray(self, dex_file.NumFieldIds())));
   if (fields.Get() == nullptr) {
+    self->AssertPendingOOMException();
     return nullptr;
   }
   dex_cache->Init(&dex_file, location.Get(), strings.Get(), types.Get(), methods.Get(),
-                  fields.Get());
+                  fields.Get(), image_pointer_size_);
   return dex_cache.Get();
 }
 
@@ -1431,7 +1500,7 @@
       heap->AllocObject<true>(self, java_lang_Class, class_size, visitor) :
       heap->AllocNonMovableObject<true>(self, java_lang_Class, class_size, visitor);
   if (UNLIKELY(k == nullptr)) {
-    CHECK(self->IsExceptionPending());  // OOME.
+    self->AssertPendingOOMException();
     return nullptr;
   }
   return k->AsClass();
@@ -1441,11 +1510,6 @@
   return AllocClass(self, GetClassRoot(kJavaLangClass), class_size);
 }
 
-mirror::ArtMethod* ClassLinker::AllocArtMethod(Thread* self) {
-  return down_cast<mirror::ArtMethod*>(
-      GetClassRoot(kJavaLangReflectArtMethod)->AllocNonMovableObject(self));
-}
-
 mirror::ObjectArray<mirror::StackTraceElement>* ClassLinker::AllocStackTraceElementArray(
     Thread* self, size_t length) {
   return mirror::ObjectArray<mirror::StackTraceElement>::Alloc(
@@ -1750,8 +1814,6 @@
       klass.Assign(GetClassRoot(kJavaLangRefReference));
     } else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) {
       klass.Assign(GetClassRoot(kJavaLangDexCache));
-    } else if (strcmp(descriptor, "Ljava/lang/reflect/ArtMethod;") == 0) {
-      klass.Assign(GetClassRoot(kJavaLangReflectArtMethod));
     }
   }
 
@@ -1897,7 +1959,8 @@
       }
     }
   }
-  return mirror::Class::ComputeClassSize(false, 0, num_8, num_16, num_32, num_64, num_ref);
+  return mirror::Class::ComputeClassSize(false, 0, num_8, num_16, num_32, num_64, num_ref,
+                                         image_pointer_size_);
 }
 
 OatFile::OatClass ClassLinker::FindOatClass(const DexFile& dex_file, uint16_t class_def_idx,
@@ -1946,7 +2009,7 @@
   UNREACHABLE();
 }
 
-const OatFile::OatMethod ClassLinker::FindOatMethodFor(mirror::ArtMethod* method, bool* found) {
+const OatFile::OatMethod ClassLinker::FindOatMethodFor(ArtMethod* method, bool* found) {
   // Although we overwrite the trampoline of non-static methods, we may get here via the resolution
   // method for direct methods (or virtual methods made direct).
   mirror::Class* declaring_class = method->GetDeclaringClass();
@@ -1963,7 +2026,7 @@
     for (size_t i = 0; i < end; i++) {
       // Check method index instead of identity in case of duplicate method definitions.
       if (method->GetDexMethodIndex() ==
-          declaring_class->GetVirtualMethod(i)->GetDexMethodIndex()) {
+          declaring_class->GetVirtualMethod(i, image_pointer_size_)->GetDexMethodIndex()) {
         found_virtual = true;
         break;
       }
@@ -1986,7 +2049,7 @@
 }
 
 // Special case to get oat code without overwriting a trampoline.
-const void* ClassLinker::GetQuickOatCodeFor(mirror::ArtMethod* method) {
+const void* ClassLinker::GetQuickOatCodeFor(ArtMethod* method) {
   CHECK(!method->IsAbstract()) << PrettyMethod(method);
   if (method->IsProxyMethod()) {
     return GetQuickProxyInvokeHandler();
@@ -2013,7 +2076,7 @@
   return GetQuickToInterpreterBridge();
 }
 
-const void* ClassLinker::GetOatMethodQuickCodeFor(mirror::ArtMethod* method) {
+const void* ClassLinker::GetOatMethodQuickCodeFor(ArtMethod* method) {
   if (method->IsNative() || method->IsAbstract() || method->IsProxyMethod()) {
     return nullptr;
   }
@@ -2044,7 +2107,7 @@
 }
 
 // Returns true if the method must run with interpreter, false otherwise.
-static bool NeedsInterpreter(mirror::ArtMethod* method, const void* quick_code)
+static bool NeedsInterpreter(ArtMethod* method, const void* quick_code)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (quick_code == nullptr) {
     // No code: need interpreter.
@@ -2089,7 +2152,7 @@
                                              &has_oat_class);
   // Link the code of methods skipped by LinkCode.
   for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) {
-    mirror::ArtMethod* method = klass->GetDirectMethod(method_index);
+    ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_);
     if (!method->IsStatic()) {
       // Only update static methods.
       continue;
@@ -2114,10 +2177,9 @@
   // Ignore virtual methods on the iterator.
 }
 
-void ClassLinker::LinkCode(Handle<mirror::ArtMethod> method,
-                           const OatFile::OatClass* oat_class,
+void ClassLinker::LinkCode(ArtMethod* method, const OatFile::OatClass* oat_class,
                            uint32_t class_def_method_index) {
-  Runtime* runtime = Runtime::Current();
+  Runtime* const runtime = Runtime::Current();
   if (runtime->IsAotCompiler()) {
     // The following code only applies to a non-compiler runtime.
     return;
@@ -2128,12 +2190,11 @@
     // Every kind of method should at least get an invoke stub from the oat_method.
     // non-abstract methods also get their code pointers.
     const OatFile::OatMethod oat_method = oat_class->GetOatMethod(class_def_method_index);
-    oat_method.LinkMethod(method.Get());
+    oat_method.LinkMethod(method);
   }
 
   // Install entry point from interpreter.
-  bool enter_interpreter = NeedsInterpreter(method.Get(),
-                                            method->GetEntryPointFromQuickCompiledCode());
+  bool enter_interpreter = NeedsInterpreter(method, method->GetEntryPointFromQuickCompiledCode());
   if (enter_interpreter && !method->IsNative()) {
     method->SetEntryPointFromInterpreter(artInterpreterToInterpreterBridge);
   } else {
@@ -2222,93 +2283,83 @@
   return ptr;
 }
 
+ArtMethod* ClassLinker::AllocArtMethodArray(Thread* self, size_t length) {
+  const size_t method_size = ArtMethod::ObjectSize(image_pointer_size_);
+  uintptr_t ptr = reinterpret_cast<uintptr_t>(
+      Runtime::Current()->GetLinearAlloc()->Alloc(self, method_size * length));
+  CHECK_NE(ptr, 0u);
+  for (size_t i = 0; i < length; ++i) {
+    new(reinterpret_cast<void*>(ptr + i * method_size)) ArtMethod;
+  }
+  return reinterpret_cast<ArtMethod*>(ptr);
+}
+
 void ClassLinker::LoadClassMembers(Thread* self, const DexFile& dex_file,
                                    const uint8_t* class_data,
                                    Handle<mirror::Class> klass,
                                    const OatFile::OatClass* oat_class) {
-  // Load static fields.
-  ClassDataItemIterator it(dex_file, class_data);
-  const size_t num_sfields = it.NumStaticFields();
-  ArtField* sfields = num_sfields != 0 ? AllocArtFieldArray(self, num_sfields) : nullptr;
-  for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
-    CHECK_LT(i, num_sfields);
-    LoadField(it, klass, &sfields[i]);
+  {
+    // Note: We cannot have thread suspension until the field and method arrays are setup or else
+    // Class::VisitFieldRoots may miss some fields or methods.
+    ScopedAssertNoThreadSuspension nts(self, __FUNCTION__);
+    // Load static fields.
+    ClassDataItemIterator it(dex_file, class_data);
+    const size_t num_sfields = it.NumStaticFields();
+    ArtField* sfields = num_sfields != 0 ? AllocArtFieldArray(self, num_sfields) : nullptr;
+    for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
+      CHECK_LT(i, num_sfields);
+      LoadField(it, klass, &sfields[i]);
+    }
+    klass->SetSFields(sfields);
+    klass->SetNumStaticFields(num_sfields);
+    DCHECK_EQ(klass->NumStaticFields(), num_sfields);
+    // Load instance fields.
+    const size_t num_ifields = it.NumInstanceFields();
+    ArtField* ifields = num_ifields != 0 ? AllocArtFieldArray(self, num_ifields) : nullptr;
+    for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) {
+      CHECK_LT(i, num_ifields);
+      LoadField(it, klass, &ifields[i]);
+    }
+    klass->SetIFields(ifields);
+    klass->SetNumInstanceFields(num_ifields);
+    DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
+    // Load methods.
+    if (it.NumDirectMethods() != 0) {
+      klass->SetDirectMethodsPtr(AllocArtMethodArray(self, it.NumDirectMethods()));
+    }
+    klass->SetNumDirectMethods(it.NumDirectMethods());
+    if (it.NumVirtualMethods() != 0) {
+      klass->SetVirtualMethodsPtr(AllocArtMethodArray(self, it.NumVirtualMethods()));
+    }
+    klass->SetNumVirtualMethods(it.NumVirtualMethods());
+    size_t class_def_method_index = 0;
+    uint32_t last_dex_method_index = DexFile::kDexNoIndex;
+    size_t last_class_def_method_index = 0;
+    for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
+      ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
+      LoadMethod(self, dex_file, it, klass, method);
+      LinkCode(method, oat_class, class_def_method_index);
+      uint32_t it_method_index = it.GetMemberIndex();
+      if (last_dex_method_index == it_method_index) {
+        // duplicate case
+        method->SetMethodIndex(last_class_def_method_index);
+      } else {
+        method->SetMethodIndex(class_def_method_index);
+        last_dex_method_index = it_method_index;
+        last_class_def_method_index = class_def_method_index;
+      }
+      class_def_method_index++;
+    }
+    for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
+      ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
+      LoadMethod(self, dex_file, it, klass, method);
+      DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
+      LinkCode(method, oat_class, class_def_method_index);
+      class_def_method_index++;
+    }
+    DCHECK(!it.HasNext());
   }
-  klass->SetSFields(sfields);
-  klass->SetNumStaticFields(num_sfields);
-  DCHECK_EQ(klass->NumStaticFields(), num_sfields);
-  // Load instance fields.
-  const size_t num_ifields = it.NumInstanceFields();
-  ArtField* ifields = num_ifields != 0 ? AllocArtFieldArray(self, num_ifields) : nullptr;
-  for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) {
-    CHECK_LT(i, num_ifields);
-    LoadField(it, klass, &ifields[i]);
-  }
-  klass->SetIFields(ifields);
-  klass->SetNumInstanceFields(num_ifields);
-  DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
-  // Note: We cannot have thread suspension until the field arrays are setup or else
-  // Class::VisitFieldRoots may miss some fields.
   self->AllowThreadSuspension();
-  // Load methods.
-  if (it.NumDirectMethods() != 0) {
-    // TODO: append direct methods to class object
-    mirror::ObjectArray<mirror::ArtMethod>* directs =
-         AllocArtMethodArray(self, it.NumDirectMethods());
-    if (UNLIKELY(directs == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return;
-    }
-    klass->SetDirectMethods(directs);
-  }
-  if (it.NumVirtualMethods() != 0) {
-    // TODO: append direct methods to class object
-    mirror::ObjectArray<mirror::ArtMethod>* virtuals =
-        AllocArtMethodArray(self, it.NumVirtualMethods());
-    if (UNLIKELY(virtuals == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return;
-    }
-    klass->SetVirtualMethods(virtuals);
-  }
-  size_t class_def_method_index = 0;
-  uint32_t last_dex_method_index = DexFile::kDexNoIndex;
-  size_t last_class_def_method_index = 0;
-  for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
-    self->AllowThreadSuspension();
-    StackHandleScope<1> hs(self);
-    Handle<mirror::ArtMethod> method(hs.NewHandle(LoadMethod(self, dex_file, it, klass)));
-    if (UNLIKELY(method.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return;
-    }
-    klass->SetDirectMethod(i, method.Get());
-    LinkCode(method, oat_class, class_def_method_index);
-    uint32_t it_method_index = it.GetMemberIndex();
-    if (last_dex_method_index == it_method_index) {
-      // duplicate case
-      method->SetMethodIndex(last_class_def_method_index);
-    } else {
-      method->SetMethodIndex(class_def_method_index);
-      last_dex_method_index = it_method_index;
-      last_class_def_method_index = class_def_method_index;
-    }
-    class_def_method_index++;
-  }
-  for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
-    self->AllowThreadSuspension();
-    StackHandleScope<1> hs(self);
-    Handle<mirror::ArtMethod> method(hs.NewHandle(LoadMethod(self, dex_file, it, klass)));
-    if (UNLIKELY(method.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return;
-    }
-    klass->SetVirtualMethod(i, method.Get());
-    DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
-    LinkCode(method, oat_class, class_def_method_index);
-    class_def_method_index++;
-  }
-  DCHECK(!it.HasNext());
 }
 
 void ClassLinker::LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass,
@@ -2319,20 +2370,12 @@
   dst->SetAccessFlags(it.GetFieldAccessFlags());
 }
 
-mirror::ArtMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file,
-                                           const ClassDataItemIterator& it,
-                                           Handle<mirror::Class> klass) {
+void ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file, const ClassDataItemIterator& it,
+                             Handle<mirror::Class> klass, ArtMethod* dst) {
   uint32_t dex_method_idx = it.GetMemberIndex();
   const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
   const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
 
-  mirror::ArtMethod* dst = AllocArtMethod(self);
-  if (UNLIKELY(dst == nullptr)) {
-    CHECK(self->IsExceptionPending());  // OOME.
-    return nullptr;
-  }
-  DCHECK(dst->IsArtMethod()) << PrettyDescriptor(dst->GetClass());
-
   ScopedAssertNoThreadSuspension ants(self, "LoadMethod");
   dst->SetDexMethodIndex(dex_method_idx);
   dst->SetDeclaringClass(klass.Get());
@@ -2378,8 +2421,6 @@
     }
   }
   dst->SetAccessFlags(access_flags);
-
-  return dst;
 }
 
 void ClassLinker::AppendToBootClassPath(Thread* self, const DexFile& dex_file) {
@@ -2483,17 +2524,17 @@
   UNREACHABLE();
 }
 
-void ClassLinker::FixupDexCaches(mirror::ArtMethod* resolution_method) {
+void ClassLinker::FixupDexCaches(ArtMethod* resolution_method) {
   ReaderMutexLock mu(Thread::Current(), dex_lock_);
-  for (size_t i = 0; i != dex_caches_.size(); ++i) {
-    mirror::DexCache* dex_cache = GetDexCache(i);
-    dex_cache->Fixup(resolution_method);
+  for (auto& dex_cache : dex_caches_) {
+    dex_cache.Read()->Fixup(resolution_method, image_pointer_size_);
   }
 }
 
 mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) {
-  mirror::Class* klass = AllocClass(self, mirror::Class::PrimitiveClassSize());
+  mirror::Class* klass = AllocClass(self, mirror::Class::PrimitiveClassSize(image_pointer_size_));
   if (UNLIKELY(klass == nullptr)) {
+    self->AssertPendingOOMException();
     return nullptr;
   }
   return InitializePrimitiveClass(klass, type);
@@ -2594,9 +2635,6 @@
       new_class.Assign(GetClassRoot(kObjectArrayClass));
     } else if (strcmp(descriptor, GetClassRootDescriptor(kJavaLangStringArrayClass)) == 0) {
       new_class.Assign(GetClassRoot(kJavaLangStringArrayClass));
-    } else if (strcmp(descriptor,
-                      GetClassRootDescriptor(kJavaLangReflectArtMethodArrayClass)) == 0) {
-      new_class.Assign(GetClassRoot(kJavaLangReflectArtMethodArrayClass));
     } else if (strcmp(descriptor, "[C") == 0) {
       new_class.Assign(GetClassRoot(kCharArrayClass));
     } else if (strcmp(descriptor, "[I") == 0) {
@@ -2606,8 +2644,9 @@
     }
   }
   if (new_class.Get() == nullptr) {
-    new_class.Assign(AllocClass(self, mirror::Array::ClassSize()));
+    new_class.Assign(AllocClass(self, mirror::Array::ClassSize(image_pointer_size_)));
     if (new_class.Get() == nullptr) {
+      self->AssertPendingOOMException();
       return nullptr;
     }
     new_class->SetComponentType(component_type.Get());
@@ -2621,9 +2660,9 @@
   new_class->SetClassLoader(component_type->GetClassLoader());
   mirror::Class::SetStatus(new_class, mirror::Class::kStatusLoaded, self);
   {
-    StackHandleScope<mirror::Class::kImtSize> hs2(self,
-                                                  Runtime::Current()->GetImtUnimplementedMethod());
-    new_class->PopulateEmbeddedImtAndVTable(&hs2);
+    ArtMethod* imt[mirror::Class::kImtSize];
+    std::fill_n(imt, arraysize(imt), Runtime::Current()->GetImtUnimplementedMethod());
+    new_class->PopulateEmbeddedImtAndVTable(imt, image_pointer_size_);
   }
   mirror::Class::SetStatus(new_class, mirror::Class::kStatusInitialized, self);
   // don't need to set new_class->SetObjectSize(..)
@@ -2733,6 +2772,18 @@
   return nullptr;
 }
 
+void ClassLinker::UpdateClassVirtualMethods(mirror::Class* klass, ArtMethod* new_methods,
+                                            size_t new_num_methods) {
+  // classlinker_classes_lock_ is used to guard against races between root marking and changing the
+  // direct and virtual method pointers.
+  WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+  klass->SetNumVirtualMethods(new_num_methods);
+  klass->SetVirtualMethodsPtr(new_methods);
+  if (log_new_class_table_roots_) {
+    new_class_roots_.push_back(GcRoot<mirror::Class>(klass));
+  }
+}
+
 mirror::Class* ClassLinker::UpdateClass(const char* descriptor, mirror::Class* klass,
                                         size_t hash) {
   WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
@@ -3074,7 +3125,7 @@
 
 void ClassLinker::EnsurePreverifiedMethods(Handle<mirror::Class> klass) {
   if (!klass->IsPreverified()) {
-    klass->SetPreverifiedFlagOnAllMethods();
+    klass->SetPreverifiedFlagOnAllMethods(image_pointer_size_);
     klass->SetPreverified();
   }
 }
@@ -3165,15 +3216,15 @@
 void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file,
                                                     Handle<mirror::Class> klass) {
   for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-    ResolveMethodExceptionHandlerTypes(dex_file, klass->GetDirectMethod(i));
+    ResolveMethodExceptionHandlerTypes(dex_file, klass->GetDirectMethod(i, image_pointer_size_));
   }
   for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
-    ResolveMethodExceptionHandlerTypes(dex_file, klass->GetVirtualMethod(i));
+    ResolveMethodExceptionHandlerTypes(dex_file, klass->GetVirtualMethod(i, image_pointer_size_));
   }
 }
 
 void ClassLinker::ResolveMethodExceptionHandlerTypes(const DexFile& dex_file,
-                                                     mirror::ArtMethod* method) {
+                                                     ArtMethod* method) {
   // similar to DexVerifier::ScanTryCatchBlocks and dex2oat's ResolveExceptionsForMethod.
   const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
   if (code_item == nullptr) {
@@ -3202,10 +3253,6 @@
   }
 }
 
-static void CheckProxyConstructor(mirror::ArtMethod* constructor);
-static void CheckProxyMethod(Handle<mirror::ArtMethod> method,
-                             Handle<mirror::ArtMethod> prototype);
-
 mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa, jstring name,
                                              jobjectArray interfaces, jobject loader,
                                              jobjectArray methods, jobjectArray throws) {
@@ -3256,48 +3303,37 @@
   throws_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
 
   // Proxies have 1 direct method, the constructor
-  {
-    StackHandleScope<2> hs2(self);
-    Handle<mirror::ObjectArray<mirror::ArtMethod>> directs =
-        hs2.NewHandle(AllocArtMethodArray(self, 1));
-    if (UNLIKELY(directs.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return nullptr;
-    }
-    klass->SetDirectMethods(directs.Get());
-    Handle<mirror::ArtMethod> constructor =
-        hs2.NewHandle(CreateProxyConstructor(self, klass));
-    if (UNLIKELY(constructor.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return nullptr;
-    }
-    klass->SetDirectMethod(0, constructor.Get());
+  auto* directs = AllocArtMethodArray(self, 1);
+  // Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we
+  // want to throw OOM in the future.
+  if (UNLIKELY(directs == nullptr)) {
+    self->AssertPendingOOMException();
+    return nullptr;
   }
+  klass->SetDirectMethodsPtr(directs);
+  klass->SetNumDirectMethods(1u);
+  CreateProxyConstructor(klass, klass->GetDirectMethodUnchecked(0, image_pointer_size_));
 
   // Create virtual method using specified prototypes.
   auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>*>(methods));
   DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass())
     << PrettyClass(h_methods->GetClass());
   const size_t num_virtual_methods = h_methods->GetLength();
-  {
-    StackHandleScope<1> hs2(self);
-    Handle<mirror::ObjectArray<mirror::ArtMethod>> virtuals =
-        hs2.NewHandle(AllocArtMethodArray(self, num_virtual_methods));
-    if (UNLIKELY(virtuals.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return nullptr;
-    }
-    klass->SetVirtualMethods(virtuals.Get());
+  auto* virtuals = AllocArtMethodArray(self, num_virtual_methods);
+  // Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we
+  // want to throw OOM in the future.
+  if (UNLIKELY(virtuals == nullptr)) {
+    self->AssertPendingOOMException();
+    return nullptr;
   }
+  klass->SetVirtualMethodsPtr(virtuals);
+  klass->SetNumVirtualMethods(num_virtual_methods);
   for (size_t i = 0; i < num_virtual_methods; ++i) {
-    StackHandleScope<2> hs2(self);
-    Handle<mirror::ArtMethod> prototype(hs2.NewHandle(h_methods->Get(i)->GetArtMethod()));
-    Handle<mirror::ArtMethod> clone(hs2.NewHandle(CreateProxyMethod(self, klass, prototype)));
-    if (UNLIKELY(clone.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return nullptr;
-    }
-    klass->SetVirtualMethod(i, clone.Get());
+    auto* virtual_method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
+    auto* prototype = h_methods->Get(i)->GetArtMethod();
+    CreateProxyMethod(klass, prototype, virtual_method);
+    DCHECK(virtual_method->GetDeclaringClass() != nullptr);
+    DCHECK(prototype->GetDeclaringClass() != nullptr);
   }
 
   // The super class is java.lang.reflect.Proxy
@@ -3312,7 +3348,7 @@
     ObjectLock<mirror::Class> resolution_lock(self, klass);
     // Link the fields and virtual methods, creating vtable and iftables.
     // The new class will replace the old one in the class table.
-    Handle<mirror::ObjectArray<mirror::Class> > h_interfaces(
+    Handle<mirror::ObjectArray<mirror::Class>> h_interfaces(
         hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces)));
     if (!LinkClass(self, descriptor.c_str(), klass, h_interfaces, &new_class)) {
       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
@@ -3339,11 +3375,11 @@
   // sanity checks
   if (kIsDebugBuild) {
     CHECK(klass->GetIFields() == nullptr);
-    CheckProxyConstructor(klass->GetDirectMethod(0));
+    CheckProxyConstructor(klass->GetDirectMethod(0, image_pointer_size_));
+
     for (size_t i = 0; i < num_virtual_methods; ++i) {
-      StackHandleScope<2> hs2(self);
-      Handle<mirror::ArtMethod> prototype(hs2.NewHandle(h_methods->Get(i)->GetArtMethod()));
-      Handle<mirror::ArtMethod> virtual_method(hs2.NewHandle(klass->GetVirtualMethod(i)));
+      auto* virtual_method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
+      auto* prototype = h_methods->Get(i++)->GetArtMethod();
       CheckProxyMethod(virtual_method, prototype);
     }
 
@@ -3372,8 +3408,8 @@
   return DotToDescriptor(name->ToModifiedUtf8().c_str());
 }
 
-mirror::ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class,
-                                                   mirror::ArtMethod* proxy_method) {
+ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class,
+                                                   ArtMethod* proxy_method) {
   DCHECK(proxy_class->IsProxyClass());
   DCHECK(proxy_method->IsProxyMethod());
   {
@@ -3382,8 +3418,8 @@
     for (const GcRoot<mirror::DexCache>& root : dex_caches_) {
       auto* dex_cache = root.Read();
       if (proxy_method->HasSameDexCacheResolvedTypes(dex_cache->GetResolvedTypes())) {
-        mirror::ArtMethod* resolved_method = dex_cache->GetResolvedMethod(
-            proxy_method->GetDexMethodIndex());
+        ArtMethod* resolved_method = dex_cache->GetResolvedMethod(
+            proxy_method->GetDexMethodIndex(), image_pointer_size_);
         CHECK(resolved_method != nullptr);
         return resolved_method;
       }
@@ -3394,74 +3430,60 @@
   UNREACHABLE();
 }
 
-
-mirror::ArtMethod* ClassLinker::CreateProxyConstructor(Thread* self,
-                                                       Handle<mirror::Class> klass) {
-  // Create constructor for Proxy that must initialize h
-  mirror::ObjectArray<mirror::ArtMethod>* proxy_direct_methods =
-      GetClassRoot(kJavaLangReflectProxy)->GetDirectMethods();
-  CHECK_EQ(proxy_direct_methods->GetLength(), 16);
-  mirror::ArtMethod* proxy_constructor = proxy_direct_methods->Get(2);
+void ClassLinker::CreateProxyConstructor(Handle<mirror::Class> klass, ArtMethod* out) {
+  // Create constructor for Proxy that must initialize the method.
+  CHECK_EQ(GetClassRoot(kJavaLangReflectProxy)->NumDirectMethods(), 16u);
+  ArtMethod* proxy_constructor = GetClassRoot(kJavaLangReflectProxy)->GetDirectMethodUnchecked(
+      2, image_pointer_size_);
   // Ensure constructor is in dex cache so that we can use the dex cache to look up the overridden
   // constructor method.
   GetClassRoot(kJavaLangReflectProxy)->GetDexCache()->SetResolvedMethod(
-      proxy_constructor->GetDexMethodIndex(), proxy_constructor);
+      proxy_constructor->GetDexMethodIndex(), proxy_constructor, image_pointer_size_);
   // Clone the existing constructor of Proxy (our constructor would just invoke it so steal its
   // code_ too)
-  mirror::ArtMethod* constructor = down_cast<mirror::ArtMethod*>(proxy_constructor->Clone(self));
-  if (constructor == nullptr) {
-    CHECK(self->IsExceptionPending());  // OOME.
-    return nullptr;
-  }
+  DCHECK(out != nullptr);
+  out->CopyFrom(proxy_constructor, image_pointer_size_);
   // Make this constructor public and fix the class to be our Proxy version
-  constructor->SetAccessFlags((constructor->GetAccessFlags() & ~kAccProtected) | kAccPublic);
-  constructor->SetDeclaringClass(klass.Get());
-  return constructor;
+  out->SetAccessFlags((out->GetAccessFlags() & ~kAccProtected) | kAccPublic);
+  out->SetDeclaringClass(klass.Get());
 }
 
-static void CheckProxyConstructor(mirror::ArtMethod* constructor)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void ClassLinker::CheckProxyConstructor(ArtMethod* constructor) const {
   CHECK(constructor->IsConstructor());
-  CHECK_STREQ(constructor->GetName(), "<init>");
-  CHECK_STREQ(constructor->GetSignature().ToString().c_str(),
-              "(Ljava/lang/reflect/InvocationHandler;)V");
+  auto* np = constructor->GetInterfaceMethodIfProxy(image_pointer_size_);
+  CHECK_STREQ(np->GetName(), "<init>");
+  CHECK_STREQ(np->GetSignature().ToString().c_str(), "(Ljava/lang/reflect/InvocationHandler;)V");
   DCHECK(constructor->IsPublic());
 }
 
-mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self,
-                                                  Handle<mirror::Class> klass,
-                                                  Handle<mirror::ArtMethod> prototype) {
+void ClassLinker::CreateProxyMethod(Handle<mirror::Class> klass, ArtMethod* prototype,
+                                    ArtMethod* out) {
   // Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
   // prototype method
   auto* dex_cache = prototype->GetDeclaringClass()->GetDexCache();
   // Avoid dirtying the dex cache unless we need to.
-  if (dex_cache->GetResolvedMethod(prototype->GetDexMethodIndex()) != prototype.Get()) {
-    dex_cache->SetResolvedMethod(prototype->GetDexMethodIndex(), prototype.Get());
+  if (dex_cache->GetResolvedMethod(prototype->GetDexMethodIndex(), image_pointer_size_) !=
+      prototype) {
+    dex_cache->SetResolvedMethod(
+        prototype->GetDexMethodIndex(), prototype, image_pointer_size_);
   }
   // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
   // as necessary
-  mirror::ArtMethod* method = down_cast<mirror::ArtMethod*>(prototype->Clone(self));
-  if (UNLIKELY(method == nullptr)) {
-    CHECK(self->IsExceptionPending());  // OOME.
-    return nullptr;
-  }
+  DCHECK(out != nullptr);
+  out->CopyFrom(prototype, image_pointer_size_);
 
   // Set class to be the concrete proxy class and clear the abstract flag, modify exceptions to
   // the intersection of throw exceptions as defined in Proxy
-  method->SetDeclaringClass(klass.Get());
-  method->SetAccessFlags((method->GetAccessFlags() & ~kAccAbstract) | kAccFinal);
+  out->SetDeclaringClass(klass.Get());
+  out->SetAccessFlags((out->GetAccessFlags() & ~kAccAbstract) | kAccFinal);
 
   // At runtime the method looks like a reference and argument saving method, clone the code
   // related parameters from this method.
-  method->SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler());
-  method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
-
-  return method;
+  out->SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler());
+  out->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
 }
 
-static void CheckProxyMethod(Handle<mirror::ArtMethod> method,
-                             Handle<mirror::ArtMethod> prototype)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void ClassLinker::CheckProxyMethod(ArtMethod* method, ArtMethod* prototype) const {
   // Basic sanity
   CHECK(!prototype->IsFinal());
   CHECK(method->IsFinal());
@@ -3469,26 +3491,26 @@
 
   // The proxy method doesn't have its own dex cache or dex file and so it steals those of its
   // interface prototype. The exception to this are Constructors and the Class of the Proxy itself.
-  CHECK(prototype->HasSameDexCacheResolvedMethods(method.Get()));
-  CHECK(prototype->HasSameDexCacheResolvedTypes(method.Get()));
-  CHECK_EQ(prototype->GetDeclaringClass()->GetDexCache(), method->GetDexCache());
+  CHECK(prototype->HasSameDexCacheResolvedMethods(method));
+  CHECK(prototype->HasSameDexCacheResolvedTypes(method));
+  auto* np = method->GetInterfaceMethodIfProxy(image_pointer_size_);
+  CHECK_EQ(prototype->GetDeclaringClass()->GetDexCache(), np->GetDexCache());
   CHECK_EQ(prototype->GetDexMethodIndex(), method->GetDexMethodIndex());
 
-  CHECK_STREQ(method->GetName(), prototype->GetName());
-  CHECK_STREQ(method->GetShorty(), prototype->GetShorty());
+  CHECK_STREQ(np->GetName(), prototype->GetName());
+  CHECK_STREQ(np->GetShorty(), prototype->GetShorty());
   // More complex sanity - via dex cache
-  CHECK_EQ(method->GetInterfaceMethodIfProxy()->GetReturnType(), prototype->GetReturnType());
+  CHECK_EQ(np->GetReturnType(), prototype->GetReturnType());
 }
 
-static bool CanWeInitializeClass(mirror::Class* klass, bool can_init_statics,
-                                 bool can_init_parents)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+bool ClassLinker::CanWeInitializeClass(mirror::Class* klass, bool can_init_statics,
+                                       bool can_init_parents) {
   if (can_init_statics && can_init_parents) {
     return true;
   }
   if (!can_init_statics) {
     // Check if there's a class initializer.
-    mirror::ArtMethod* clinit = klass->FindClassInitializer();
+    ArtMethod* clinit = klass->FindClassInitializer(image_pointer_size_);
     if (clinit != nullptr) {
       return false;
     }
@@ -3501,17 +3523,14 @@
       }
     }
   }
-  if (!klass->IsInterface() && klass->HasSuperClass()) {
-    mirror::Class* super_class = klass->GetSuperClass();
-    if (!can_init_parents && !super_class->IsInitialized()) {
-      return false;
-    } else {
-      if (!CanWeInitializeClass(super_class, can_init_statics, can_init_parents)) {
-        return false;
-      }
-    }
+  if (klass->IsInterface() || !klass->HasSuperClass()) {
+    return true;
   }
-  return true;
+  mirror::Class* super_class = klass->GetSuperClass();
+  if (!can_init_parents && !super_class->IsInitialized()) {
+    return false;
+  }
+  return CanWeInitializeClass(super_class, can_init_statics, can_init_parents);
 }
 
 bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
@@ -3671,7 +3690,7 @@
     }
   }
 
-  mirror::ArtMethod* clinit = klass->FindClassInitializer();
+  ArtMethod* clinit = klass->FindClassInitializer(image_pointer_size_);
   if (clinit != nullptr) {
     CHECK(can_init_statics);
     JValue result;
@@ -3762,8 +3781,8 @@
 
 static void ThrowSignatureCheckResolveReturnTypeException(Handle<mirror::Class> klass,
                                                           Handle<mirror::Class> super_klass,
-                                                          Handle<mirror::ArtMethod> method,
-                                                          mirror::ArtMethod* m)
+                                                          ArtMethod* method,
+                                                          ArtMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(Thread::Current()->IsExceptionPending());
   DCHECK(!m->IsProxyMethod());
@@ -3777,7 +3796,7 @@
                            "While checking class %s method %s signature against %s %s: "
                            "Failed to resolve return type %s with %s",
                            PrettyDescriptor(klass.Get()).c_str(),
-                           PrettyMethod(method.Get()).c_str(),
+                           PrettyMethod(method).c_str(),
                            super_klass->IsInterface() ? "interface" : "superclass",
                            PrettyDescriptor(super_klass.Get()).c_str(),
                            return_type.c_str(), class_loader.c_str());
@@ -3785,8 +3804,8 @@
 
 static void ThrowSignatureCheckResolveArgException(Handle<mirror::Class> klass,
                                                    Handle<mirror::Class> super_klass,
-                                                   Handle<mirror::ArtMethod> method,
-                                                   mirror::ArtMethod* m,
+                                                   ArtMethod* method,
+                                                   ArtMethod* m,
                                                    uint32_t index, uint32_t arg_type_idx)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(Thread::Current()->IsExceptionPending());
@@ -3798,7 +3817,7 @@
                            "While checking class %s method %s signature against %s %s: "
                            "Failed to resolve arg %u type %s with %s",
                            PrettyDescriptor(klass.Get()).c_str(),
-                           PrettyMethod(method.Get()).c_str(),
+                           PrettyMethod(method).c_str(),
                            super_klass->IsInterface() ? "interface" : "superclass",
                            PrettyDescriptor(super_klass.Get()).c_str(),
                            index, arg_type.c_str(), class_loader.c_str());
@@ -3806,13 +3825,13 @@
 
 static void ThrowSignatureMismatch(Handle<mirror::Class> klass,
                                    Handle<mirror::Class> super_klass,
-                                   Handle<mirror::ArtMethod> method,
+                                   ArtMethod* method,
                                    const std::string& error_msg)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ThrowLinkageError(klass.Get(),
                     "Class %s method %s resolves differently in %s %s: %s",
                     PrettyDescriptor(klass.Get()).c_str(),
-                    PrettyMethod(method.Get()).c_str(),
+                    PrettyMethod(method).c_str(),
                     super_klass->IsInterface() ? "interface" : "superclass",
                     PrettyDescriptor(super_klass.Get()).c_str(),
                     error_msg.c_str());
@@ -3821,19 +3840,19 @@
 static bool HasSameSignatureWithDifferentClassLoaders(Thread* self,
                                                       Handle<mirror::Class> klass,
                                                       Handle<mirror::Class> super_klass,
-                                                      Handle<mirror::ArtMethod> method1,
-                                                      Handle<mirror::ArtMethod> method2)
+                                                      ArtMethod* method1,
+                                                      ArtMethod* method2)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   {
     StackHandleScope<1> hs(self);
     Handle<mirror::Class> return_type(hs.NewHandle(method1->GetReturnType()));
     if (UNLIKELY(return_type.Get() == nullptr)) {
-      ThrowSignatureCheckResolveReturnTypeException(klass, super_klass, method1, method1.Get());
+      ThrowSignatureCheckResolveReturnTypeException(klass, super_klass, method1, method1);
       return false;
     }
     mirror::Class* other_return_type = method2->GetReturnType();
     if (UNLIKELY(other_return_type == nullptr)) {
-      ThrowSignatureCheckResolveReturnTypeException(klass, super_klass, method1, method2.Get());
+      ThrowSignatureCheckResolveReturnTypeException(klass, super_klass, method1, method2);
       return false;
     }
     if (UNLIKELY(other_return_type != return_type.Get())) {
@@ -3852,7 +3871,7 @@
     if (types2 != nullptr && types2->Size() != 0) {
       ThrowSignatureMismatch(klass, super_klass, method1,
                              StringPrintf("Type list mismatch with %s",
-                                          PrettyMethod(method2.Get(), true).c_str()));
+                                          PrettyMethod(method2, true).c_str()));
       return false;
     }
     return true;
@@ -3860,7 +3879,7 @@
     if (types1->Size() != 0) {
       ThrowSignatureMismatch(klass, super_klass, method1,
                              StringPrintf("Type list mismatch with %s",
-                                          PrettyMethod(method2.Get(), true).c_str()));
+                                          PrettyMethod(method2, true).c_str()));
       return false;
     }
     return true;
@@ -3869,7 +3888,7 @@
   if (UNLIKELY(num_types != types2->Size())) {
     ThrowSignatureMismatch(klass, super_klass, method1,
                            StringPrintf("Type list mismatch with %s",
-                                        PrettyMethod(method2.Get(), true).c_str()));
+                                        PrettyMethod(method2, true).c_str()));
     return false;
   }
   for (uint32_t i = 0; i < num_types; ++i) {
@@ -3879,7 +3898,7 @@
         method1->GetClassFromTypeIndex(param_type_idx, true)));
     if (UNLIKELY(param_type.Get() == nullptr)) {
       ThrowSignatureCheckResolveArgException(klass, super_klass, method1,
-                                             method1.Get(), i, param_type_idx);
+                                             method1, i, param_type_idx);
       return false;
     }
     uint32_t other_param_type_idx = types2->GetTypeItem(i).type_idx_;
@@ -3887,7 +3906,7 @@
         method2->GetClassFromTypeIndex(other_param_type_idx, true);
     if (UNLIKELY(other_param_type == nullptr)) {
       ThrowSignatureCheckResolveArgException(klass, super_klass, method1,
-                                             method2.Get(), i, other_param_type_idx);
+                                             method2, i, other_param_type_idx);
       return false;
     }
     if (UNLIKELY(param_type.Get() != other_param_type)) {
@@ -3911,19 +3930,17 @@
   }
   // Begin with the methods local to the superclass.
   Thread* self = Thread::Current();
-  StackHandleScope<3> hs(self);
+  StackHandleScope<1> hs(self);
   MutableHandle<mirror::Class> super_klass(hs.NewHandle<mirror::Class>(nullptr));
-  MutableHandle<mirror::ArtMethod> h_m(hs.NewHandle<mirror::ArtMethod>(nullptr));
-  MutableHandle<mirror::ArtMethod> super_h_m(hs.NewHandle<mirror::ArtMethod>(nullptr));
   if (klass->HasSuperClass() &&
       klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
     super_klass.Assign(klass->GetSuperClass());
     for (int i = klass->GetSuperClass()->GetVTableLength() - 1; i >= 0; --i) {
-      h_m.Assign(klass->GetVTableEntry(i));
-      super_h_m.Assign(klass->GetSuperClass()->GetVTableEntry(i));
-      if (h_m.Get() != super_h_m.Get()) {
+      auto* m = klass->GetVTableEntry(i, image_pointer_size_);
+      auto* super_m = klass->GetSuperClass()->GetVTableEntry(i, image_pointer_size_);
+      if (m != super_m) {
         if (UNLIKELY(!HasSameSignatureWithDifferentClassLoaders(self, klass, super_klass,
-                                                                h_m, super_h_m))) {
+                                                                m, super_m))) {
           self->AssertPendingException();
           return false;
         }
@@ -3935,11 +3952,12 @@
     if (klass->GetClassLoader() != super_klass->GetClassLoader()) {
       uint32_t num_methods = super_klass->NumVirtualMethods();
       for (uint32_t j = 0; j < num_methods; ++j) {
-        h_m.Assign(klass->GetIfTable()->GetMethodArray(i)->GetWithoutChecks(j));
-        super_h_m.Assign(super_klass->GetVirtualMethod(j));
-        if (h_m.Get() != super_h_m.Get()) {
+        auto* m = klass->GetIfTable()->GetMethodArray(i)->GetElementPtrSize<ArtMethod*>(
+            j, image_pointer_size_);
+        auto* super_m = super_klass->GetVirtualMethod(j, image_pointer_size_);
+        if (m != super_m) {
           if (UNLIKELY(!HasSameSignatureWithDifferentClassLoaders(self, klass, super_klass,
-                                                                  h_m, super_h_m))) {
+                                                                  m, super_m))) {
             self->AssertPendingException();
             return false;
           }
@@ -3968,8 +3986,10 @@
   return success;
 }
 
-void ClassLinker::FixupTemporaryDeclaringClass(mirror::Class* temp_class, mirror::Class* new_class) {
+void ClassLinker::FixupTemporaryDeclaringClass(mirror::Class* temp_class,
+                                               mirror::Class* new_class) {
   ArtField* fields = new_class->GetIFields();
+  DCHECK_EQ(temp_class->NumInstanceFields(), new_class->NumInstanceFields());
   for (size_t i = 0, count = new_class->NumInstanceFields(); i < count; i++) {
     if (fields[i].GetDeclaringClass() == temp_class) {
       fields[i].SetDeclaringClass(new_class);
@@ -3977,27 +3997,24 @@
   }
 
   fields = new_class->GetSFields();
+  DCHECK_EQ(temp_class->NumStaticFields(), new_class->NumStaticFields());
   for (size_t i = 0, count = new_class->NumStaticFields(); i < count; i++) {
     if (fields[i].GetDeclaringClass() == temp_class) {
       fields[i].SetDeclaringClass(new_class);
     }
   }
 
-  mirror::ObjectArray<mirror::ArtMethod>* methods = new_class->GetDirectMethods();
-  if (methods != nullptr) {
-    for (int index = 0; index < methods->GetLength(); index ++) {
-      if (methods->Get(index)->GetDeclaringClass() == temp_class) {
-        methods->Get(index)->SetDeclaringClass(new_class);
-      }
+  DCHECK_EQ(temp_class->NumDirectMethods(), new_class->NumDirectMethods());
+  for (auto& method : new_class->GetDirectMethods(image_pointer_size_)) {
+    if (method.GetDeclaringClass() == temp_class) {
+      method.SetDeclaringClass(new_class);
     }
   }
 
-  methods = new_class->GetVirtualMethods();
-  if (methods != nullptr) {
-    for (int index = 0; index < methods->GetLength(); index ++) {
-      if (methods->Get(index)->GetDeclaringClass() == temp_class) {
-        methods->Get(index)->SetDeclaringClass(new_class);
-      }
+  DCHECK_EQ(temp_class->NumVirtualMethods(), new_class->NumVirtualMethods());
+  for (auto& method : new_class->GetVirtualMethods(image_pointer_size_)) {
+    if (method.GetDeclaringClass() == temp_class) {
+      method.SetDeclaringClass(new_class);
     }
   }
 }
@@ -4010,9 +4027,9 @@
   if (!LinkSuperClass(klass)) {
     return false;
   }
-  StackHandleScope<mirror::Class::kImtSize> imt_handle_scope(
-      self, Runtime::Current()->GetImtUnimplementedMethod());
-  if (!LinkMethods(self, klass, interfaces, &imt_handle_scope)) {
+  ArtMethod* imt[mirror::Class::kImtSize];
+  std::fill_n(imt, arraysize(imt), Runtime::Current()->GetImtUnimplementedMethod());
+  if (!LinkMethods(self, klass, interfaces, imt)) {
     return false;
   }
   if (!LinkInstanceFields(self, klass)) {
@@ -4031,7 +4048,7 @@
     CHECK_EQ(klass->GetClassSize(), class_size) << PrettyDescriptor(klass.Get());
 
     if (klass->ShouldHaveEmbeddedImtAndVTable()) {
-      klass->PopulateEmbeddedImtAndVTable(&imt_handle_scope);
+      klass->PopulateEmbeddedImtAndVTable(imt, image_pointer_size_);
     }
 
     // This will notify waiters on klass that saw the not yet resolved
@@ -4042,10 +4059,9 @@
     CHECK(!klass->IsResolved());
     // Retire the temporary class and create the correctly sized resolved class.
     StackHandleScope<1> hs(self);
-    auto h_new_class = hs.NewHandle<mirror::Class>(
-        klass->CopyOf(self, class_size, &imt_handle_scope));
+    auto h_new_class = hs.NewHandle(klass->CopyOf(self, class_size, imt, image_pointer_size_));
     if (UNLIKELY(h_new_class.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // Expect an OOME.
+      self->AssertPendingOOMException();
       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
       return false;
     }
@@ -4357,7 +4373,7 @@
 // Populate the class vtable and itable. Compute return type indices.
 bool ClassLinker::LinkMethods(Thread* self, Handle<mirror::Class> klass,
                               Handle<mirror::ObjectArray<mirror::Class>> interfaces,
-                              StackHandleScope<mirror::Class::kImtSize>* out_imt) {
+                              ArtMethod** out_imt) {
   self->AllowThreadSuspension();
   if (klass->IsInterface()) {
     // No vtable.
@@ -4367,7 +4383,7 @@
       return false;
     }
     for (size_t i = 0; i < count; ++i) {
-      klass->GetVirtualMethodDuringLinking(i)->SetMethodIndex(i);
+      klass->GetVirtualMethodDuringLinking(i, image_pointer_size_)->SetMethodIndex(i);
     }
   } else if (!LinkVirtualMethods(self, klass)) {  // Link virtual methods first.
     return false;
@@ -4380,7 +4396,7 @@
 // caches in the implementation below.
 class MethodNameAndSignatureComparator FINAL : public ValueObject {
  public:
-  explicit MethodNameAndSignatureComparator(mirror::ArtMethod* method)
+  explicit MethodNameAndSignatureComparator(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
       dex_file_(method->GetDexFile()), mid_(&dex_file_->GetMethodId(method->GetDexMethodIndex())),
       name_(nullptr), name_len_(0) {
@@ -4394,7 +4410,7 @@
     return name_;
   }
 
-  bool HasSameNameAndSignature(mirror::ArtMethod* other)
+  bool HasSameNameAndSignature(ArtMethod* other)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(!other->IsProxyMethod()) << PrettyMethod(other);
     const DexFile* other_dex_file = other->GetDexFile();
@@ -4425,13 +4441,16 @@
 
 class LinkVirtualHashTable {
  public:
-  LinkVirtualHashTable(Handle<mirror::Class> klass, size_t hash_size, uint32_t* hash_table)
-     : klass_(klass), hash_size_(hash_size), hash_table_(hash_table) {
+  LinkVirtualHashTable(Handle<mirror::Class> klass, size_t hash_size, uint32_t* hash_table,
+                       size_t image_pointer_size)
+     : klass_(klass), hash_size_(hash_size), hash_table_(hash_table),
+       image_pointer_size_(image_pointer_size) {
     std::fill(hash_table_, hash_table_ + hash_size_, invalid_index_);
   }
   void Add(uint32_t virtual_method_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* local_method = klass_->GetVirtualMethodDuringLinking(virtual_method_index);
-    const char* name = local_method->GetName();
+    ArtMethod* local_method = klass_->GetVirtualMethodDuringLinking(
+        virtual_method_index, image_pointer_size_);
+    const char* name = local_method->GetInterfaceMethodIfProxy(image_pointer_size_)->GetName();
     uint32_t hash = ComputeModifiedUtf8Hash(name);
     uint32_t index = hash % hash_size_;
     // Linear probe until we have an empty slot.
@@ -4455,9 +4474,10 @@
         break;
       }
       if (value != removed_index_) {  // This signifies not already overriden.
-        mirror::ArtMethod* virtual_method =
-            klass_->GetVirtualMethodDuringLinking(value);
-        if (comparator->HasSameNameAndSignature(virtual_method->GetInterfaceMethodIfProxy())) {
+        ArtMethod* virtual_method =
+            klass_->GetVirtualMethodDuringLinking(value, image_pointer_size_);
+        if (comparator->HasSameNameAndSignature(
+            virtual_method->GetInterfaceMethodIfProxy(image_pointer_size_))) {
           hash_table_[index] = removed_index_;
           return value;
         }
@@ -4479,6 +4499,7 @@
   Handle<mirror::Class> klass_;
   const size_t hash_size_;
   uint32_t* const hash_table_;
+  const size_t image_pointer_size_;
 };
 
 const uint32_t LinkVirtualHashTable::invalid_index_ = std::numeric_limits<uint32_t>::max();
@@ -4491,30 +4512,32 @@
     const size_t max_count = num_virtual_methods + super_vtable_length;
     StackHandleScope<2> hs(self);
     Handle<mirror::Class> super_class(hs.NewHandle(klass->GetSuperClass()));
-    MutableHandle<mirror::ObjectArray<mirror::ArtMethod>> vtable;
+    MutableHandle<mirror::PointerArray> vtable;
     if (super_class->ShouldHaveEmbeddedImtAndVTable()) {
-      vtable = hs.NewHandle(AllocArtMethodArray(self, max_count));
+      vtable = hs.NewHandle(AllocPointerArray(self, max_count));
       if (UNLIKELY(vtable.Get() == nullptr)) {
-        CHECK(self->IsExceptionPending());  // OOME.
+        self->AssertPendingOOMException();
         return false;
       }
       for (size_t i = 0; i < super_vtable_length; i++) {
-        vtable->SetWithoutChecks<false>(i, super_class->GetEmbeddedVTableEntry(i));
+        vtable->SetElementPtrSize(
+            i, super_class->GetEmbeddedVTableEntry(i, image_pointer_size_), image_pointer_size_);
       }
       if (num_virtual_methods == 0) {
         klass->SetVTable(vtable.Get());
         return true;
       }
     } else {
-      mirror::ObjectArray<mirror::ArtMethod>* super_vtable = super_class->GetVTable();
+      auto* super_vtable = super_class->GetVTable();
       CHECK(super_vtable != nullptr) << PrettyClass(super_class.Get());
       if (num_virtual_methods == 0) {
         klass->SetVTable(super_vtable);
         return true;
       }
-      vtable = hs.NewHandle(super_vtable->CopyOf(self, max_count));
+      vtable = hs.NewHandle(down_cast<mirror::PointerArray*>(
+          super_vtable->CopyOf(self, max_count)));
       if (UNLIKELY(vtable.Get() == nullptr)) {
-        CHECK(self->IsExceptionPending());  // OOME.
+        self->AssertPendingOOMException();
         return false;
       }
     }
@@ -4538,21 +4561,24 @@
       hash_heap_storage.reset(new uint32_t[hash_table_size]);
       hash_table_ptr = hash_heap_storage.get();
     }
-    LinkVirtualHashTable hash_table(klass, hash_table_size, hash_table_ptr);
+    LinkVirtualHashTable hash_table(klass, hash_table_size, hash_table_ptr, image_pointer_size_);
     // Add virtual methods to the hash table.
     for (size_t i = 0; i < num_virtual_methods; ++i) {
+      DCHECK(klass->GetVirtualMethodDuringLinking(
+          i, image_pointer_size_)->GetDeclaringClass() != nullptr);
       hash_table.Add(i);
     }
     // Loop through each super vtable method and see if they are overriden by a method we added to
     // the hash table.
     for (size_t j = 0; j < super_vtable_length; ++j) {
       // Search the hash table to see if we are overidden by any method.
-      mirror::ArtMethod* super_method = vtable->GetWithoutChecks(j);
+      ArtMethod* super_method = vtable->GetElementPtrSize<ArtMethod*>(j, image_pointer_size_);
       MethodNameAndSignatureComparator super_method_name_comparator(
-          super_method->GetInterfaceMethodIfProxy());
+          super_method->GetInterfaceMethodIfProxy(image_pointer_size_));
       uint32_t hash_index = hash_table.FindAndRemove(&super_method_name_comparator);
       if (hash_index != hash_table.GetNotFoundIndex()) {
-        mirror::ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(hash_index);
+        ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(
+            hash_index, image_pointer_size_);
         if (klass->CanAccessMember(super_method->GetDeclaringClass(),
                                    super_method->GetAccessFlags())) {
           if (super_method->IsFinal()) {
@@ -4561,7 +4587,7 @@
                               super_method->GetDeclaringClassDescriptor());
             return false;
           }
-          vtable->SetWithoutChecks<false>(j, virtual_method);
+          vtable->SetElementPtrSize(j, virtual_method, image_pointer_size_);
           virtual_method->SetMethodIndex(j);
         } else {
           LOG(WARNING) << "Before Android 4.1, method " << PrettyMethod(virtual_method)
@@ -4573,13 +4599,13 @@
     // Add the non overridden methods at the end.
     size_t actual_count = super_vtable_length;
     for (size_t i = 0; i < num_virtual_methods; ++i) {
-      mirror::ArtMethod* local_method = klass->GetVirtualMethodDuringLinking(i);
+      ArtMethod* local_method = klass->GetVirtualMethodDuringLinking(i, image_pointer_size_);
       size_t method_idx = local_method->GetMethodIndexDuringLinking();
       if (method_idx < super_vtable_length &&
-          local_method == vtable->GetWithoutChecks(method_idx)) {
+          local_method == vtable->GetElementPtrSize<ArtMethod*>(method_idx, image_pointer_size_)) {
         continue;
       }
-      vtable->SetWithoutChecks<false>(actual_count, local_method);
+      vtable->SetElementPtrSize(actual_count, local_method, image_pointer_size_);
       local_method->SetMethodIndex(actual_count);
       ++actual_count;
     }
@@ -4590,9 +4616,9 @@
     // Shrink vtable if possible
     CHECK_LE(actual_count, max_count);
     if (actual_count < max_count) {
-      vtable.Assign(vtable->CopyOf(self, actual_count));
+      vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, actual_count)));
       if (UNLIKELY(vtable.Get() == nullptr)) {
-        CHECK(self->IsExceptionPending());  // OOME.
+        self->AssertPendingOOMException();
         return false;
       }
     }
@@ -4604,14 +4630,14 @@
                             static_cast<int>(num_virtual_methods));
       return false;
     }
-    mirror::ObjectArray<mirror::ArtMethod>* vtable = AllocArtMethodArray(self, num_virtual_methods);
+    auto* vtable = AllocPointerArray(self, num_virtual_methods);
     if (UNLIKELY(vtable == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
+      self->AssertPendingOOMException();
       return false;
     }
     for (size_t i = 0; i < num_virtual_methods; ++i) {
-      mirror::ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i);
-      vtable->SetWithoutChecks<false>(i, virtual_method);
+      ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i, image_pointer_size_);
+      vtable->SetElementPtrSize(i, virtual_method, image_pointer_size_);
       virtual_method->SetMethodIndex(i & 0xFFFF);
     }
     klass->SetVTable(vtable);
@@ -4621,7 +4647,7 @@
 
 bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass,
                                        Handle<mirror::ObjectArray<mirror::Class>> interfaces,
-                                       StackHandleScope<mirror::Class::kImtSize>* out_imt) {
+                                       ArtMethod** out_imt) {
   StackHandleScope<3> hs(self);
   Runtime* const runtime = Runtime::Current();
   const bool has_superclass = klass->HasSuperClass();
@@ -4629,6 +4655,7 @@
   const bool have_interfaces = interfaces.Get() != nullptr;
   const size_t num_interfaces =
       have_interfaces ? interfaces->GetLength() : klass->NumDirectInterfaces();
+  const size_t method_size = ArtMethod::ObjectSize(image_pointer_size_);
   if (num_interfaces == 0) {
     if (super_ifcount == 0) {
       // Class implements no interfaces.
@@ -4667,7 +4694,7 @@
   }
   MutableHandle<mirror::IfTable> iftable(hs.NewHandle(AllocIfTable(self, ifcount)));
   if (UNLIKELY(iftable.Get() == nullptr)) {
-    CHECK(self->IsExceptionPending());  // OOME.
+    self->AssertPendingOOMException();
     return false;
   }
   if (super_ifcount != 0) {
@@ -4716,9 +4743,10 @@
   // Shrink iftable in case duplicates were found
   if (idx < ifcount) {
     DCHECK_NE(num_interfaces, 0U);
-    iftable.Assign(down_cast<mirror::IfTable*>(iftable->CopyOf(self, idx * mirror::IfTable::kMax)));
+    iftable.Assign(down_cast<mirror::IfTable*>(
+        iftable->CopyOf(self, idx * mirror::IfTable::kMax)));
     if (UNLIKELY(iftable.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
+      self->AssertPendingOOMException();
       return false;
     }
     ifcount = idx;
@@ -4730,15 +4758,18 @@
   if (klass->IsInterface()) {
     return true;
   }
-  size_t miranda_list_size = 0;
-  size_t max_miranda_methods = 0;  // The max size of miranda_list.
-  for (size_t i = 0; i < ifcount; ++i) {
-    max_miranda_methods += iftable->GetInterface(i)->NumVirtualMethods();
-  }
-  MutableHandle<mirror::ObjectArray<mirror::ArtMethod>>
-      miranda_list(hs.NewHandle(AllocArtMethodArray(self, max_miranda_methods)));
-  MutableHandle<mirror::ObjectArray<mirror::ArtMethod>> vtable(
-      hs.NewHandle(klass->GetVTableDuringLinking()));
+  // These are allocated on the heap to begin, we then transfer to linear alloc when we re-create
+  // the virtual methods array.
+  // Need to use low 4GB arenas for compiler or else the pointers wont fit in 32 bit method array
+  // during cross compilation.
+  // Use the linear alloc pool since this one is in the low 4gb for the compiler.
+  ArenaStack stack(runtime->GetLinearAlloc()->GetArenaPool());
+  ScopedArenaAllocator allocator(&stack);
+  ScopedArenaVector<ArtMethod*> miranda_methods(allocator.Adapter());
+
+  MutableHandle<mirror::PointerArray> vtable(hs.NewHandle(klass->GetVTableDuringLinking()));
+  ArtMethod* const unimplemented_method = runtime->GetImtUnimplementedMethod();
+  ArtMethod* const conflict_method = runtime->GetImtConflictMethod();
   // Copy the IMT from the super class if possible.
   bool extend_super_iftable = false;
   if (has_superclass) {
@@ -4746,12 +4777,11 @@
     extend_super_iftable = true;
     if (super_class->ShouldHaveEmbeddedImtAndVTable()) {
       for (size_t i = 0; i < mirror::Class::kImtSize; ++i) {
-        out_imt->SetReference(i, super_class->GetEmbeddedImTableEntry(i));
+        out_imt[i] = super_class->GetEmbeddedImTableEntry(i, image_pointer_size_);
       }
     } else {
       // No imt in the super class, need to reconstruct from the iftable.
       mirror::IfTable* if_table = super_class->GetIfTable();
-      mirror::ArtMethod* conflict_method = runtime->GetImtConflictMethod();
       const size_t length = super_class->GetIfTableCount();
       for (size_t i = 0; i < length; ++i) {
         mirror::Class* interface = iftable->GetInterface(i);
@@ -4761,63 +4791,84 @@
         if (method_array_count == 0) {
           continue;
         }
-        mirror::ObjectArray<mirror::ArtMethod>* method_array = if_table->GetMethodArray(i);
+        auto* method_array = if_table->GetMethodArray(i);
         for (size_t j = 0; j < num_virtuals; ++j) {
-          mirror::ArtMethod* method = method_array->GetWithoutChecks(j);
+          auto method = method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size_);
+          DCHECK(method != nullptr) << PrettyClass(super_class);
           if (method->IsMiranda()) {
             continue;
           }
-          mirror::ArtMethod* interface_method = interface->GetVirtualMethod(j);
+          ArtMethod* interface_method = interface->GetVirtualMethod(j, image_pointer_size_);
           uint32_t imt_index = interface_method->GetDexMethodIndex() % mirror::Class::kImtSize;
-          mirror::ArtMethod* imt_ref = out_imt->GetReference(imt_index)->AsArtMethod();
-          if (imt_ref == runtime->GetImtUnimplementedMethod()) {
-            out_imt->SetReference(imt_index, method);
+          auto*& imt_ref = out_imt[imt_index];
+          if (imt_ref == unimplemented_method) {
+            imt_ref = method;
           } else if (imt_ref != conflict_method) {
-            out_imt->SetReference(imt_index, conflict_method);
+            imt_ref = conflict_method;
           }
         }
       }
     }
   }
+  // Allocate method arrays before since we don't want miss visiting miranda method roots due to
+  // thread suspension.
   for (size_t i = 0; i < ifcount; ++i) {
-    self->AllowThreadSuspension();
     size_t num_methods = iftable->GetInterface(i)->NumVirtualMethods();
     if (num_methods > 0) {
-      StackHandleScope<2> hs2(self);
       const bool is_super = i < super_ifcount;
       const bool super_interface = is_super && extend_super_iftable;
-      Handle<mirror::ObjectArray<mirror::ArtMethod>> method_array;
-      Handle<mirror::ObjectArray<mirror::ArtMethod>> input_array;
+      mirror::PointerArray* method_array;
       if (super_interface) {
         mirror::IfTable* if_table = klass->GetSuperClass()->GetIfTable();
         DCHECK(if_table != nullptr);
         DCHECK(if_table->GetMethodArray(i) != nullptr);
         // If we are working on a super interface, try extending the existing method array.
-        method_array = hs2.NewHandle(if_table->GetMethodArray(i)->Clone(self)->
-            AsObjectArray<mirror::ArtMethod>());
-        // We are overwriting a super class interface, try to only virtual methods instead of the
-        // whole vtable.
-        input_array = hs2.NewHandle(klass->GetVirtualMethods());
+        method_array = down_cast<mirror::PointerArray*>(if_table->GetMethodArray(i)->Clone(self));
       } else {
-        method_array = hs2.NewHandle(AllocArtMethodArray(self, num_methods));
-        // A new interface, we need the whole vtable incase a new interface method is implemented
-        // in the whole superclass.
-        input_array = vtable;
+        method_array = AllocPointerArray(self, num_methods);
       }
-      if (UNLIKELY(method_array.Get() == nullptr)) {
-        CHECK(self->IsExceptionPending());  // OOME.
+      if (UNLIKELY(method_array == nullptr)) {
+        self->AssertPendingOOMException();
         return false;
       }
-      iftable->SetMethodArray(i, method_array.Get());
-      if (input_array.Get() == nullptr) {
+      iftable->SetMethodArray(i, method_array);
+    }
+  }
+
+  auto* old_cause = self->StartAssertNoThreadSuspension(
+      "Copying ArtMethods for LinkInterfaceMethods");
+  for (size_t i = 0; i < ifcount; ++i) {
+    size_t num_methods = iftable->GetInterface(i)->NumVirtualMethods();
+    if (num_methods > 0) {
+      StackHandleScope<2> hs2(self);
+      const bool is_super = i < super_ifcount;
+      const bool super_interface = is_super && extend_super_iftable;
+      auto method_array(hs2.NewHandle(iftable->GetMethodArray(i)));
+
+      ArtMethod* input_virtual_methods = nullptr;
+      Handle<mirror::PointerArray> input_vtable_array = NullHandle<mirror::PointerArray>();
+      int32_t input_array_length = 0;
+      if (super_interface) {
+        // We are overwriting a super class interface, try to only virtual methods instead of the
+        // whole vtable.
+        input_virtual_methods = klass->GetVirtualMethodsPtr();
+        input_array_length = klass->NumVirtualMethods();
+      } else {
+        // A new interface, we need the whole vtable in case a new interface method is implemented
+        // in the whole superclass.
+        input_vtable_array = vtable;
+        input_array_length = input_vtable_array->GetLength();
+      }
+      if (input_array_length == 0) {
         // If the added virtual methods is empty, do nothing.
         DCHECK(super_interface);
         continue;
       }
       for (size_t j = 0; j < num_methods; ++j) {
-        mirror::ArtMethod* interface_method = iftable->GetInterface(i)->GetVirtualMethod(j);
+        auto* interface_method = iftable->GetInterface(i)->GetVirtualMethod(
+            j, image_pointer_size_);
         MethodNameAndSignatureComparator interface_name_comparator(
-            interface_method->GetInterfaceMethodIfProxy());
+            interface_method->GetInterfaceMethodIfProxy(image_pointer_size_));
         int32_t k;
         // For each method listed in the interface's method list, find the
         // matching method in our class's method list.  We want to favor the
@@ -4827,108 +4878,161 @@
         // it -- otherwise it would use the same vtable slot.  In .dex files
         // those don't end up in the virtual method table, so it shouldn't
         // matter which direction we go.  We walk it backward anyway.)
-        for (k = input_array->GetLength() - 1; k >= 0; --k) {
-          mirror::ArtMethod* vtable_method = input_array->GetWithoutChecks(k);
-          mirror::ArtMethod* vtable_method_for_name_comparison =
-              vtable_method->GetInterfaceMethodIfProxy();
+        for (k = input_array_length - 1; k >= 0; --k) {
+          ArtMethod* vtable_method = input_virtual_methods != nullptr ?
+              reinterpret_cast<ArtMethod*>(
+                  reinterpret_cast<uintptr_t>(input_virtual_methods) + method_size * k) :
+              input_vtable_array->GetElementPtrSize<ArtMethod*>(k, image_pointer_size_);
+          ArtMethod* vtable_method_for_name_comparison =
+              vtable_method->GetInterfaceMethodIfProxy(image_pointer_size_);
           if (interface_name_comparator.HasSameNameAndSignature(
               vtable_method_for_name_comparison)) {
             if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) {
-              ThrowIllegalAccessError(
-                  klass.Get(),
+              ThrowIllegalAccessError(klass.Get(),
                   "Method '%s' implementing interface method '%s' is not public",
-                  PrettyMethod(vtable_method).c_str(),
-                  PrettyMethod(interface_method).c_str());
+                  PrettyMethod(vtable_method).c_str(), PrettyMethod(interface_method).c_str());
               return false;
             }
-            method_array->SetWithoutChecks<false>(j, vtable_method);
+            method_array->SetElementPtrSize(j, vtable_method, image_pointer_size_);
             // Place method in imt if entry is empty, place conflict otherwise.
             uint32_t imt_index = interface_method->GetDexMethodIndex() % mirror::Class::kImtSize;
-            mirror::ArtMethod* imt_ref = out_imt->GetReference(imt_index)->AsArtMethod();
-            mirror::ArtMethod* conflict_method = runtime->GetImtConflictMethod();
-            if (imt_ref == runtime->GetImtUnimplementedMethod()) {
-              out_imt->SetReference(imt_index, vtable_method);
-            } else if (imt_ref != conflict_method) {
+            auto** imt_ref = &out_imt[imt_index];
+            if (*imt_ref == unimplemented_method) {
+              *imt_ref = vtable_method;
+            } else if (*imt_ref != conflict_method) {
               // If we are not a conflict and we have the same signature and name as the imt entry,
               // it must be that we overwrote a superclass vtable entry.
-              MethodNameAndSignatureComparator imt_ref_name_comparator(
-                  imt_ref->GetInterfaceMethodIfProxy());
-              if (imt_ref_name_comparator.HasSameNameAndSignature(
-                  vtable_method_for_name_comparison)) {
-                out_imt->SetReference(imt_index, vtable_method);
-              } else {
-                out_imt->SetReference(imt_index, conflict_method);
-              }
+              MethodNameAndSignatureComparator imt_comparator(
+                  (*imt_ref)->GetInterfaceMethodIfProxy(image_pointer_size_));
+              *imt_ref = imt_comparator.HasSameNameAndSignature(vtable_method_for_name_comparison) ?
+                  vtable_method : conflict_method;
             }
             break;
           }
         }
         if (k < 0 && !super_interface) {
-          mirror::ArtMethod* miranda_method = nullptr;
-          for (size_t l = 0; l < miranda_list_size; ++l) {
-            mirror::ArtMethod* mir_method = miranda_list->Get(l);
+          ArtMethod* miranda_method = nullptr;
+          for (auto& mir_method : miranda_methods) {
             if (interface_name_comparator.HasSameNameAndSignature(mir_method)) {
               miranda_method = mir_method;
               break;
             }
           }
           if (miranda_method == nullptr) {
+            size_t size = ArtMethod::ObjectSize(image_pointer_size_);
+            miranda_method = reinterpret_cast<ArtMethod*>(allocator.Alloc(size));
+            CHECK(miranda_method != nullptr);
             // Point the interface table at a phantom slot.
-            miranda_method = interface_method->Clone(self)->AsArtMethod();
-            if (UNLIKELY(miranda_method == nullptr)) {
-              CHECK(self->IsExceptionPending());  // OOME.
-              return false;
-            }
-            DCHECK_LT(miranda_list_size, max_miranda_methods);
-            miranda_list->Set<false>(miranda_list_size++, miranda_method);
+            new(miranda_method) ArtMethod(*interface_method, image_pointer_size_);
+            miranda_methods.push_back(miranda_method);
           }
-          method_array->SetWithoutChecks<false>(j, miranda_method);
+          method_array->SetElementPtrSize(j, miranda_method, image_pointer_size_);
         }
       }
     }
   }
-  if (miranda_list_size > 0) {
-    int old_method_count = klass->NumVirtualMethods();
-    int new_method_count = old_method_count + miranda_list_size;
-    mirror::ObjectArray<mirror::ArtMethod>* virtuals;
-    if (old_method_count == 0) {
-      virtuals = AllocArtMethodArray(self, new_method_count);
-    } else {
-      virtuals = klass->GetVirtualMethods()->CopyOf(self, new_method_count);
-    }
+  if (!miranda_methods.empty()) {
+    const size_t old_method_count = klass->NumVirtualMethods();
+    const size_t new_method_count = old_method_count + miranda_methods.size();
+    // Attempt to realloc to save RAM if possible.
+    ArtMethod* old_virtuals = klass->GetVirtualMethodsPtr();
+    // The Realloced virtual methods aren't visiblef from the class roots, so there is no issue
+    // where GCs could attempt to mark stale pointers due to memcpy. And since we overwrite the
+    // realloced memory with out->CopyFrom, we are guaranteed to have objects in the to space since
+    // CopyFrom has internal read barriers.
+    auto* virtuals = reinterpret_cast<ArtMethod*>(runtime->GetLinearAlloc()->Realloc(
+        self, old_virtuals, old_method_count * method_size, new_method_count * method_size));
     if (UNLIKELY(virtuals == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
+      self->AssertPendingOOMException();
       return false;
     }
-    klass->SetVirtualMethods(virtuals);
+    ScopedArenaUnorderedMap<ArtMethod*, ArtMethod*> move_table(allocator.Adapter());
+    if (virtuals != old_virtuals) {
+      // Maps from heap allocated miranda method to linear alloc miranda method.
+      StrideIterator<ArtMethod> out(reinterpret_cast<uintptr_t>(virtuals), method_size);
+      // Copy over the old methods + miranda methods.
+      for (auto& m : klass->GetVirtualMethods(image_pointer_size_)) {
+        move_table.emplace(&m, &*out);
+        // The CopyFrom is only necessary to not miss read barriers since Realloc won't do read
+        // barriers when it copies.
+        out->CopyFrom(&m, image_pointer_size_);
+        ++out;
+      }
+    }
+    UpdateClassVirtualMethods(klass.Get(), virtuals, new_method_count);
+    // Done copying methods, they are all reachable from the class now, so we can end the no thread
+    // suspension assert.
+    self->EndAssertNoThreadSuspension(old_cause);
 
-    int old_vtable_count = vtable->GetLength();
-    int new_vtable_count = old_vtable_count + miranda_list_size;
-    vtable.Assign(vtable->CopyOf(self, new_vtable_count));
+    size_t old_vtable_count = vtable->GetLength();
+    const size_t new_vtable_count = old_vtable_count + miranda_methods.size();
+    vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, new_vtable_count)));
     if (UNLIKELY(vtable.Get() == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
+      self->AssertPendingOOMException();
       return false;
     }
-    for (size_t i = 0; i < miranda_list_size; ++i) {
-      mirror::ArtMethod* method = miranda_list->Get(i);
+    StrideIterator<ArtMethod> out(
+        reinterpret_cast<uintptr_t>(virtuals) + old_method_count * method_size, method_size);
+    for (auto* mir_method : miranda_methods) {
+      ArtMethod* out_method = &*out;
+      out->CopyFrom(mir_method, image_pointer_size_);
       // Leave the declaring class alone as type indices are relative to it
-      method->SetAccessFlags(method->GetAccessFlags() | kAccMiranda);
-      method->SetMethodIndex(0xFFFF & (old_vtable_count + i));
-      klass->SetVirtualMethod(old_method_count + i, method);
-      vtable->SetWithoutChecks<false>(old_vtable_count + i, method);
+      out_method->SetAccessFlags(out_method->GetAccessFlags() | kAccMiranda);
+      out_method->SetMethodIndex(0xFFFF & old_vtable_count);
+      vtable->SetElementPtrSize(old_vtable_count, out_method, image_pointer_size_);
+      move_table.emplace(mir_method, out_method);
+      ++out;
+      ++old_vtable_count;
     }
-    // TODO: do not assign to the vtable field until it is fully constructed.
+
+    // Update old vtable methods.
+    for (size_t i = 0; i < old_vtable_count - miranda_methods.size(); ++i) {
+      auto* m = vtable->GetElementPtrSize<ArtMethod*>(i, image_pointer_size_);
+      DCHECK(m != nullptr) << PrettyClass(klass.Get());
+      auto it = move_table.find(m);
+      if (it != move_table.end()) {
+        auto* new_m = it->second;
+        DCHECK(new_m != nullptr) << PrettyClass(klass.Get());
+        vtable->SetElementPtrSize(i, new_m, image_pointer_size_);
+      }
+    }
     klass->SetVTable(vtable.Get());
+    CHECK_EQ(old_vtable_count, new_vtable_count);
+    // Go fix up all the stale miranda pointers.
+    for (size_t i = 0; i < ifcount; ++i) {
+      for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
+        auto* method_array = iftable->GetMethodArray(i);
+        auto* m = method_array->GetElementPtrSize<ArtMethod*>(j, image_pointer_size_);
+        DCHECK(m != nullptr) << PrettyClass(klass.Get());
+        auto it = move_table.find(m);
+        if (it != move_table.end()) {
+          auto* new_m = it->second;
+          DCHECK(new_m != nullptr) << PrettyClass(klass.Get());
+          method_array->SetElementPtrSize(j, new_m, image_pointer_size_);
+        }
+      }
+    }
+    // Check that there are no stale methods are in the dex cache array.
+    if (kIsDebugBuild) {
+      auto* resolved_methods = klass->GetDexCache()->GetResolvedMethods();
+      for (size_t i = 0, count = resolved_methods->GetLength(); i < count; ++i) {
+        auto* m = resolved_methods->GetElementPtrSize<ArtMethod*>(i, image_pointer_size_);
+        CHECK(move_table.find(m) == move_table.end()) << PrettyMethod(m);
+      }
+    }
+    // Put some random garbage in old virtuals to help find stale pointers.
+    if (virtuals != old_virtuals) {
+      memset(old_virtuals, 0xFEu, ArtMethod::ObjectSize(image_pointer_size_) * old_method_count);
+    }
+  } else {
+    self->EndAssertNoThreadSuspension(old_cause);
   }
-
   if (kIsDebugBuild) {
-    mirror::ObjectArray<mirror::ArtMethod>* check_vtable = klass->GetVTableDuringLinking();
+    auto* check_vtable = klass->GetVTableDuringLinking();
     for (int i = 0; i < check_vtable->GetLength(); ++i) {
-      CHECK(check_vtable->GetWithoutChecks(i) != nullptr);
+      CHECK(check_vtable->GetElementPtrSize<ArtMethod*>(i, image_pointer_size_) != nullptr);
     }
   }
-
-  self->AllowThreadSuspension();
   return true;
 }
 
@@ -4985,7 +5089,7 @@
   // Initialize field_offset
   MemberOffset field_offset(0);
   if (is_static) {
-    field_offset = klass->GetFirstReferenceStaticFieldOffsetDuringLinking();
+    field_offset = klass->GetFirstReferenceStaticFieldOffsetDuringLinking(image_pointer_size_);
   } else {
     mirror::Class* super_class = klass->GetSuperClass();
     if (super_class != nullptr) {
@@ -5060,19 +5164,14 @@
   } else {
     klass->SetNumReferenceInstanceFields(num_reference_fields);
     if (!klass->IsVariableSize()) {
-      if (klass->DescriptorEquals("Ljava/lang/reflect/ArtMethod;")) {
-        size_t pointer_size = GetInstructionSetPointerSize(Runtime::Current()->GetInstructionSet());
-        klass->SetObjectSize(mirror::ArtMethod::InstanceSize(pointer_size));
-      } else {
-        std::string temp;
-        DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor(&temp);
-        size_t previous_size = klass->GetObjectSize();
-        if (previous_size != 0) {
-          // Make sure that we didn't originally have an incorrect size.
-          CHECK_EQ(previous_size, size) << klass->GetDescriptor(&temp);
-        }
-        klass->SetObjectSize(size);
+      std::string temp;
+      DCHECK_GE(size, sizeof(mirror::Object)) << klass->GetDescriptor(&temp);
+      size_t previous_size = klass->GetObjectSize();
+      if (previous_size != 0) {
+        // Make sure that we didn't originally have an incorrect size.
+        CHECK_EQ(previous_size, size) << klass->GetDescriptor(&temp);
       }
+      klass->SetObjectSize(size);
     }
   }
 
@@ -5080,7 +5179,7 @@
     // Make sure that the fields array is ordered by name but all reference
     // offsets are at the beginning as far as alignment allows.
     MemberOffset start_ref_offset = is_static
-        ? klass->GetFirstReferenceStaticFieldOffsetDuringLinking()
+        ? klass->GetFirstReferenceStaticFieldOffsetDuringLinking(image_pointer_size_)
         : klass->GetFirstReferenceInstanceFieldOffset();
     MemberOffset end_ref_offset(start_ref_offset.Uint32Value() +
                                 num_reference_fields *
@@ -5204,19 +5303,19 @@
     }
   }
   DCHECK((resolved == nullptr) || resolved->IsResolved() || resolved->IsErroneous())
-          << PrettyDescriptor(resolved) << " " << resolved->GetStatus();
+      << PrettyDescriptor(resolved) << " " << resolved->GetStatus();
   return resolved;
 }
 
-mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, uint32_t method_idx,
-                                              Handle<mirror::DexCache> dex_cache,
-                                              Handle<mirror::ClassLoader> class_loader,
-                                              Handle<mirror::ArtMethod> referrer,
-                                              InvokeType type) {
+ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file, uint32_t method_idx,
+                                      Handle<mirror::DexCache> dex_cache,
+                                      Handle<mirror::ClassLoader> class_loader,
+                                      ArtMethod* referrer, InvokeType type) {
   DCHECK(dex_cache.Get() != nullptr);
   // Check for hit in the dex cache.
-  mirror::ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx);
+  ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, image_pointer_size_);
   if (resolved != nullptr && !resolved->IsRuntimeMethod()) {
+    DCHECK(resolved->GetDeclaringClassUnchecked() != nullptr) << resolved->GetDexMethodIndex();
     return resolved;
   }
   // Fail, get the declaring class.
@@ -5231,15 +5330,16 @@
   switch (type) {
     case kDirect:  // Fall-through.
     case kStatic:
-      resolved = klass->FindDirectMethod(dex_cache.Get(), method_idx);
+      resolved = klass->FindDirectMethod(dex_cache.Get(), method_idx, image_pointer_size_);
+      DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr);
       break;
     case kInterface:
-      resolved = klass->FindInterfaceMethod(dex_cache.Get(), method_idx);
+      resolved = klass->FindInterfaceMethod(dex_cache.Get(), method_idx, image_pointer_size_);
       DCHECK(resolved == nullptr || resolved->GetDeclaringClass()->IsInterface());
       break;
     case kSuper:  // Fall-through.
     case kVirtual:
-      resolved = klass->FindVirtualMethod(dex_cache.Get(), method_idx);
+      resolved = klass->FindVirtualMethod(dex_cache.Get(), method_idx, image_pointer_size_);
       break;
     default:
       LOG(FATAL) << "Unreachable - invocation type: " << type;
@@ -5252,27 +5352,28 @@
     switch (type) {
       case kDirect:  // Fall-through.
       case kStatic:
-        resolved = klass->FindDirectMethod(name, signature);
+        resolved = klass->FindDirectMethod(name, signature, image_pointer_size_);
+        DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr);
         break;
       case kInterface:
-        resolved = klass->FindInterfaceMethod(name, signature);
+        resolved = klass->FindInterfaceMethod(name, signature, image_pointer_size_);
         DCHECK(resolved == nullptr || resolved->GetDeclaringClass()->IsInterface());
         break;
       case kSuper:  // Fall-through.
       case kVirtual:
-        resolved = klass->FindVirtualMethod(name, signature);
+        resolved = klass->FindVirtualMethod(name, signature, image_pointer_size_);
         break;
     }
   }
   // If we found a method, check for incompatible class changes.
   if (LIKELY(resolved != nullptr && !resolved->CheckIncompatibleClassChange(type))) {
     // Be a good citizen and update the dex cache to speed subsequent calls.
-    dex_cache->SetResolvedMethod(method_idx, resolved);
+    dex_cache->SetResolvedMethod(method_idx, resolved, image_pointer_size_);
     return resolved;
   } else {
     // If we had a method, it's an incompatible-class-change error.
     if (resolved != nullptr) {
-      ThrowIncompatibleClassChangeError(type, resolved->GetInvokeType(), resolved, referrer.Get());
+      ThrowIncompatibleClassChangeError(type, resolved->GetInvokeType(), resolved, referrer);
     } else {
       // We failed to find the method which means either an access error, an incompatible class
       // change, or no such method. First try to find the method among direct and virtual methods.
@@ -5281,28 +5382,27 @@
       switch (type) {
         case kDirect:
         case kStatic:
-          resolved = klass->FindVirtualMethod(name, signature);
+          resolved = klass->FindVirtualMethod(name, signature, image_pointer_size_);
           // Note: kDirect and kStatic are also mutually exclusive, but in that case we would
           //       have had a resolved method before, which triggers the "true" branch above.
           break;
         case kInterface:
         case kVirtual:
         case kSuper:
-          resolved = klass->FindDirectMethod(name, signature);
+          resolved = klass->FindDirectMethod(name, signature, image_pointer_size_);
           break;
       }
 
       // If we found something, check that it can be accessed by the referrer.
       bool exception_generated = false;
-      if (resolved != nullptr && referrer.Get() != nullptr) {
+      if (resolved != nullptr && referrer != nullptr) {
         mirror::Class* methods_class = resolved->GetDeclaringClass();
         mirror::Class* referring_class = referrer->GetDeclaringClass();
         if (!referring_class->CanAccess(methods_class)) {
-          ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
-                                                        resolved, type);
+          ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class, resolved,
+                                                        type);
           exception_generated = true;
-        } else if (!referring_class->CanAccessMember(methods_class,
-                                                     resolved->GetAccessFlags())) {
+        } else if (!referring_class->CanAccessMember(methods_class, resolved->GetAccessFlags())) {
           ThrowIllegalAccessErrorMethod(referring_class, resolved);
           exception_generated = true;
         }
@@ -5315,11 +5415,11 @@
           case kDirect:
           case kStatic:
             if (resolved != nullptr) {
-              ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get());
+              ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer);
             } else {
-              resolved = klass->FindInterfaceMethod(name, signature);
+              resolved = klass->FindInterfaceMethod(name, signature, image_pointer_size_);
               if (resolved != nullptr) {
-                ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get());
+                ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer);
               } else {
                 ThrowNoSuchMethodError(type, klass, name, signature);
               }
@@ -5327,11 +5427,11 @@
             break;
           case kInterface:
             if (resolved != nullptr) {
-              ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
+              ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer);
             } else {
-              resolved = klass->FindVirtualMethod(name, signature);
+              resolved = klass->FindVirtualMethod(name, signature, image_pointer_size_);
               if (resolved != nullptr) {
-                ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer.Get());
+                ThrowIncompatibleClassChangeError(type, kVirtual, resolved, referrer);
               } else {
                 ThrowNoSuchMethodError(type, klass, name, signature);
               }
@@ -5339,18 +5439,18 @@
             break;
           case kSuper:
             if (resolved != nullptr) {
-              ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
+              ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer);
             } else {
               ThrowNoSuchMethodError(type, klass, name, signature);
             }
             break;
           case kVirtual:
             if (resolved != nullptr) {
-              ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer.Get());
+              ThrowIncompatibleClassChangeError(type, kDirect, resolved, referrer);
             } else {
-              resolved = klass->FindInterfaceMethod(name, signature);
+              resolved = klass->FindInterfaceMethod(name, signature, image_pointer_size_);
               if (resolved != nullptr) {
-                ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer.Get());
+                ThrowIncompatibleClassChangeError(type, kInterface, resolved, referrer);
               } else {
                 ThrowNoSuchMethodError(type, klass, name, signature);
               }
@@ -5435,7 +5535,7 @@
   return resolved;
 }
 
-const char* ClassLinker::MethodShorty(uint32_t method_idx, mirror::ArtMethod* referrer,
+const char* ClassLinker::MethodShorty(uint32_t method_idx, ArtMethod* referrer,
                                       uint32_t* length) {
   mirror::Class* declaring_class = referrer->GetDeclaringClass();
   mirror::DexCache* dex_cache = declaring_class->GetDexCache();
@@ -5490,14 +5590,14 @@
   return GetQuickGenericJniStub();
 }
 
-void ClassLinker::SetEntryPointsToCompiledCode(mirror::ArtMethod* method,
+void ClassLinker::SetEntryPointsToCompiledCode(ArtMethod* method,
                                                const void* method_code) const {
   OatFile::OatMethod oat_method = CreateOatMethod(method_code);
   oat_method.LinkMethod(method);
   method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
 }
 
-void ClassLinker::SetEntryPointsToInterpreter(mirror::ArtMethod* method) const {
+void ClassLinker::SetEntryPointsToInterpreter(ArtMethod* method) const {
   if (!method->IsNative()) {
     method->SetEntryPointFromInterpreter(artInterpreterToInterpreterBridge);
     method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
@@ -5558,13 +5658,11 @@
     "Ljava/lang/String;",
     "Ljava/lang/DexCache;",
     "Ljava/lang/ref/Reference;",
-    "Ljava/lang/reflect/ArtMethod;",
     "Ljava/lang/reflect/Constructor;",
     "Ljava/lang/reflect/Field;",
     "Ljava/lang/reflect/Method;",
     "Ljava/lang/reflect/Proxy;",
     "[Ljava/lang/String;",
-    "[Ljava/lang/reflect/ArtMethod;",
     "[Ljava/lang/reflect/Constructor;",
     "[Ljava/lang/reflect/Field;",
     "[Ljava/lang/reflect/Method;",
@@ -5636,7 +5734,7 @@
   return ComputeModifiedUtf8Hash(descriptor);
 }
 
-bool ClassLinker::MayBeCalledWithDirectCodePointer(mirror::ArtMethod* m) {
+bool ClassLinker::MayBeCalledWithDirectCodePointer(ArtMethod* m) {
   if (Runtime::Current()->UseJit()) {
     // JIT can have direct code pointers from any method to any other method.
     return true;
@@ -5758,4 +5856,12 @@
   return soa.Env()->NewGlobalRef(local_ref.get());
 }
 
+ArtMethod* ClassLinker::CreateRuntimeMethod() {
+  ArtMethod* method = AllocArtMethodArray(Thread::Current(), 1);
+  CHECK(method != nullptr);
+  method->SetDexMethodIndex(DexFile::kDexNoIndex);
+  CHECK(method->IsRuntimeMethod());
+  return method;
+}
+
 }  // namespace art
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 947e152..fa8b2e7 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -42,6 +42,7 @@
 namespace mirror {
   class ClassLoader;
   class DexCache;
+  class DexCachePointerArray;
   class DexCacheTest_Open_Test;
   class IfTable;
   template<class T> class ObjectArray;
@@ -71,13 +72,11 @@
     kJavaLangString,
     kJavaLangDexCache,
     kJavaLangRefReference,
-    kJavaLangReflectArtMethod,
     kJavaLangReflectConstructor,
     kJavaLangReflectField,
     kJavaLangReflectMethod,
     kJavaLangReflectProxy,
     kJavaLangStringArrayClass,
-    kJavaLangReflectArtMethodArrayClass,
     kJavaLangReflectConstructorArrayClass,
     kJavaLangReflectFieldArrayClass,
     kJavaLangReflectMethodArrayClass,
@@ -187,7 +186,7 @@
   // Resolve a String with the given index from the DexFile, storing the
   // result in the DexCache. The referrer is used to identify the
   // target DexCache and ClassLoader to use for resolution.
-  mirror::String* ResolveString(uint32_t string_idx, mirror::ArtMethod* referrer)
+  mirror::String* ResolveString(uint32_t string_idx, ArtMethod* referrer)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Resolve a String with the given index from the DexFile, storing the
@@ -205,7 +204,7 @@
   // Resolve a Type with the given index from the DexFile, storing the
   // result in the DexCache. The referrer is used to identify the
   // target DexCache and ClassLoader to use for resolution.
-  mirror::Class* ResolveType(uint16_t type_idx, mirror::ArtMethod* referrer)
+  mirror::Class* ResolveType(uint16_t type_idx, ArtMethod* referrer)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::Class* ResolveType(uint16_t type_idx, ArtField* referrer)
@@ -225,25 +224,22 @@
   // in ResolveType. What is unique is the method type argument which
   // is used to determine if this method is a direct, static, or
   // virtual method.
-  mirror::ArtMethod* ResolveMethod(const DexFile& dex_file,
-                                   uint32_t method_idx,
-                                   Handle<mirror::DexCache> dex_cache,
-                                   Handle<mirror::ClassLoader> class_loader,
-                                   Handle<mirror::ArtMethod> referrer,
-                                   InvokeType type)
+  ArtMethod* ResolveMethod(const DexFile& dex_file, uint32_t method_idx,
+                           Handle<mirror::DexCache> dex_cache,
+                           Handle<mirror::ClassLoader> class_loader, ArtMethod* referrer,
+                           InvokeType type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtMethod* GetResolvedMethod(uint32_t method_idx, mirror::ArtMethod* referrer)
+  ArtMethod* GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  mirror::ArtMethod* ResolveMethod(Thread* self, uint32_t method_idx, mirror::ArtMethod** referrer,
-                                   InvokeType type)
+  ArtMethod* ResolveMethod(Thread* self, uint32_t method_idx, ArtMethod* referrer, InvokeType type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   ArtField* GetResolvedField(uint32_t field_idx, mirror::Class* field_declaring_class)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   ArtField* GetResolvedField(uint32_t field_idx, mirror::DexCache* dex_cache)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  ArtField* ResolveField(uint32_t field_idx, mirror::ArtMethod* referrer, bool is_static)
+  ArtField* ResolveField(uint32_t field_idx, ArtMethod* referrer, bool is_static)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Resolve a field with a given ID from the DexFile, storing the
@@ -263,12 +259,12 @@
   // in ResolveType. No is_static argument is provided so that Java
   // field resolution semantics are followed.
   ArtField* ResolveFieldJLS(const DexFile& dex_file, uint32_t field_idx,
-                                    Handle<mirror::DexCache> dex_cache,
-                                    Handle<mirror::ClassLoader> class_loader)
+                            Handle<mirror::DexCache> dex_cache,
+                            Handle<mirror::ClassLoader> class_loader)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get shorty from method index without resolution. Used to do handlerization.
-  const char* MethodShorty(uint32_t method_idx, mirror::ArtMethod* referrer, uint32_t* length)
+  const char* MethodShorty(uint32_t method_idx, ArtMethod* referrer, uint32_t* length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns true on success, false if there's an exception pending.
@@ -323,7 +319,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool IsDexFileRegistered(const DexFile& dex_file)
       LOCKS_EXCLUDED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void FixupDexCaches(mirror::ArtMethod* resolution_method)
+  void FixupDexCaches(ArtMethod* resolution_method)
       LOCKS_EXCLUDED(dex_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -360,7 +356,9 @@
   mirror::ObjectArray<mirror::String>* AllocStringArray(Thread* self, size_t length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ObjectArray<mirror::ArtMethod>* AllocArtMethodArray(Thread* self, size_t length)
+  ArtMethod* AllocArtMethodArray(Thread* self, size_t length);
+
+  mirror::PointerArray* AllocPointerArray(Thread* self, size_t length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::IfTable* AllocIfTable(Thread* self, size_t ifcount)
@@ -381,7 +379,7 @@
   void ResolveClassExceptionHandlerTypes(const DexFile& dex_file,
                                          Handle<mirror::Class> klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, mirror::ArtMethod* klass)
+  void ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, ArtMethod* klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::Class* CreateProxyClass(ScopedObjectAccessAlreadyRunnable& soa, jstring name,
@@ -390,23 +388,23 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   std::string GetDescriptorForProxy(mirror::Class* proxy_class)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  mirror::ArtMethod* FindMethodForProxy(mirror::Class* proxy_class,
-                                        mirror::ArtMethod* proxy_method)
+  ArtMethod* FindMethodForProxy(mirror::Class* proxy_class, ArtMethod* proxy_method)
       LOCKS_EXCLUDED(dex_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get the oat code for a method when its class isn't yet initialized
-  const void* GetQuickOatCodeFor(mirror::ArtMethod* method)
+  const void* GetQuickOatCodeFor(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get the oat code for a method from a method index.
-  const void* GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx)
+  const void* GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
+                                 uint32_t method_idx)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get compiled code for a method, return null if no code
   // exists. This is unlike Get..OatCodeFor which will return a bridge
   // or interpreter entrypoint.
-  const void* GetOatMethodQuickCodeFor(mirror::ArtMethod* method)
+  const void* GetOatMethodQuickCodeFor(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   pid_t GetClassesLockOwner();  // For SignalCatcher.
@@ -430,11 +428,11 @@
   }
 
   // Set the entrypoints up for method to the given code.
-  void SetEntryPointsToCompiledCode(mirror::ArtMethod* method, const void* method_code) const
+  void SetEntryPointsToCompiledCode(ArtMethod* method, const void* method_code) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Set the entrypoints up for method to the enter the interpreter.
-  void SetEntryPointsToInterpreter(mirror::ArtMethod* method) const
+  void SetEntryPointsToInterpreter(ArtMethod* method) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Attempts to insert a class into a class table.  Returns null if
@@ -444,9 +442,6 @@
       LOCKS_EXCLUDED(Locks::classlinker_classes_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  // Special code to allocate an art method, use this instead of class->AllocObject.
-  mirror::ArtMethod* AllocArtMethod(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   mirror::ObjectArray<mirror::Class>* GetClassRoots() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read();
     DCHECK(class_roots != nullptr);
@@ -465,7 +460,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns true if the method can be called with its direct code pointer, false otherwise.
-  bool MayBeCalledWithDirectCodePointer(mirror::ArtMethod* m)
+  bool MayBeCalledWithDirectCodePointer(ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Creates a GlobalRef PathClassLoader that can be used to load classes from the given dex files.
@@ -473,11 +468,20 @@
   jobject CreatePathClassLoader(Thread* self, std::vector<const DexFile*>& dex_files)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
- private:
-  static void InitFromImageInterpretOnlyCallback(mirror::Object* obj, void* arg)
+  size_t GetImagePointerSize() const {
+    DCHECK(ValidPointerSize(image_pointer_size_)) << image_pointer_size_;
+    return image_pointer_size_;
+  }
+
+  // Used by image writer for checking.
+  bool ClassInClassTable(mirror::Class* klass)
+      LOCKS_EXCLUDED(Locks::classlinker_classes_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  const OatFile::OatMethod FindOatMethodFor(mirror::ArtMethod* method, bool* found)
+  ArtMethod* CreateRuntimeMethod();
+
+ private:
+  const OatFile::OatMethod FindOatMethodFor(ArtMethod* method, bool* found)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   OatFile& GetImageOatFile(gc::space::ImageSpace* space)
@@ -535,9 +539,8 @@
                  ArtField* dst)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtMethod* LoadMethod(Thread* self, const DexFile& dex_file,
-                                const ClassDataItemIterator& dex_method,
-                                Handle<mirror::Class> klass)
+  void LoadMethod(Thread* self, const DexFile& dex_file, const ClassDataItemIterator& it,
+                  Handle<mirror::Class> klass, ArtMethod* dst)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void FixupStaticTrampolines(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -566,9 +569,8 @@
                                                 Handle<mirror::ClassLoader> class_loader2)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool IsSameMethodSignatureInDifferentClassContexts(Thread* self, mirror::ArtMethod* method,
-                                                     mirror::Class* klass1,
-                                                     mirror::Class* klass2)
+  bool IsSameMethodSignatureInDifferentClassContexts(Thread* self, ArtMethod* method,
+                                                     mirror::Class* klass1, mirror::Class* klass2)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool LinkClass(Thread* self, const char* descriptor, Handle<mirror::Class> klass,
@@ -584,15 +586,15 @@
 
   bool LinkMethods(Thread* self, Handle<mirror::Class> klass,
                    Handle<mirror::ObjectArray<mirror::Class>> interfaces,
-                   StackHandleScope<mirror::Class::kImtSize>* out_imt)
+                   ArtMethod** out_imt)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool LinkVirtualMethods(Thread* self, Handle<mirror::Class> klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool LinkInterfaceMethods(Thread* const self, Handle<mirror::Class> klass,
+  bool LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass,
                             Handle<mirror::ObjectArray<mirror::Class>> interfaces,
-                            StackHandleScope<mirror::Class::kImtSize>* out_imt)
+                            ArtMethod** out_imt)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool LinkStaticFields(Thread* self, Handle<mirror::Class> klass, size_t* class_size)
@@ -601,12 +603,17 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool LinkFields(Thread* self, Handle<mirror::Class> klass, bool is_static, size_t* class_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void LinkCode(Handle<mirror::ArtMethod> method, const OatFile::OatClass* oat_class,
+  void LinkCode(ArtMethod* method, const OatFile::OatClass* oat_class,
                 uint32_t class_def_method_index)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void CreateReferenceInstanceOffsets(Handle<mirror::Class> klass)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  void CheckProxyConstructor(ArtMethod* constructor) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void CheckProxyMethod(ArtMethod* method, ArtMethod* prototype) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // For use by ImageWriter to find DexCaches for its roots
   ReaderWriterMutex* DexLock()
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCK_RETURNED(dex_lock_) {
@@ -623,10 +630,9 @@
   // Returns the boot image oat file.
   const OatFile* GetBootOatFile() SHARED_LOCKS_REQUIRED(dex_lock_);
 
-  mirror::ArtMethod* CreateProxyConstructor(Thread* self, Handle<mirror::Class> klass)
+  void CreateProxyConstructor(Handle<mirror::Class> klass, ArtMethod* out)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  mirror::ArtMethod* CreateProxyMethod(Thread* self, Handle<mirror::Class> klass,
-                                       Handle<mirror::ArtMethod> prototype)
+  void CreateProxyMethod(Handle<mirror::Class> klass, ArtMethod* prototype, ArtMethod* out)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Ensures that methods have the kAccPreverified bit set. We use the kAccPreverfied bit on the
@@ -673,6 +679,16 @@
   // Check for duplicate class definitions of the given oat file against all open oat files.
   bool HasCollisions(const OatFile* oat_file, std::string* error_msg) LOCKS_EXCLUDED(dex_lock_);
 
+  bool HasInitWithString(Thread* self, ClassLinker* class_linker, const char* descriptor)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  bool CanWeInitializeClass(mirror::Class* klass, bool can_init_statics, bool can_init_parents)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void UpdateClassVirtualMethods(mirror::Class* klass, ArtMethod* new_methods,
+                                 size_t new_num_methods)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(Locks::classlinker_classes_lock_);
+
   std::vector<const DexFile*> boot_class_path_;
   std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
 
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index d155941..a4e0227 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -20,6 +20,7 @@
 #include <string>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "dex_file.h"
@@ -27,7 +28,6 @@
 #include "gc/heap.h"
 #include "mirror/abstract_method.h"
 #include "mirror/accessible_object.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
 #include "mirror/field.h"
@@ -159,9 +159,9 @@
     EXPECT_EQ(class_linker_->FindArrayClass(self, &array_ptr), array.Get());
   }
 
-  void AssertMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void AssertMethod(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     EXPECT_TRUE(method != nullptr);
-    EXPECT_TRUE(method->GetClass() != nullptr);
+    EXPECT_TRUE(method->GetDeclaringClass() != nullptr);
     EXPECT_TRUE(method->GetName() != nullptr);
     EXPECT_TRUE(method->GetSignature() != Signature::NoSignature());
 
@@ -208,8 +208,8 @@
     if (klass->IsInterface()) {
       EXPECT_TRUE(klass->IsAbstract());
       if (klass->NumDirectMethods() == 1) {
-        EXPECT_TRUE(klass->GetDirectMethod(0)->IsClassInitializer());
-        EXPECT_TRUE(klass->GetDirectMethod(0)->IsDirect());
+        EXPECT_TRUE(klass->GetDirectMethod(0, sizeof(void*))->IsClassInitializer());
+        EXPECT_TRUE(klass->GetDirectMethod(0, sizeof(void*))->IsDirect());
       } else {
         EXPECT_EQ(0U, klass->NumDirectMethods());
       }
@@ -246,18 +246,16 @@
     EXPECT_FALSE(klass->IsPrimitive());
     EXPECT_TRUE(klass->CanAccess(klass.Get()));
 
-    for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-      mirror::ArtMethod* method = klass->GetDirectMethod(i);
-      AssertMethod(method);
-      EXPECT_TRUE(method->IsDirect());
-      EXPECT_EQ(klass.Get(), method->GetDeclaringClass());
+    for (ArtMethod& method : klass->GetDirectMethods(sizeof(void*))) {
+      AssertMethod(&method);
+      EXPECT_TRUE(method.IsDirect());
+      EXPECT_EQ(klass.Get(), method.GetDeclaringClass());
     }
 
-    for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
-      mirror::ArtMethod* method = klass->GetVirtualMethod(i);
-      AssertMethod(method);
-      EXPECT_FALSE(method->IsDirect());
-      EXPECT_TRUE(method->GetDeclaringClass()->IsAssignableFrom(klass.Get()));
+    for (ArtMethod& method : klass->GetVirtualMethods(sizeof(void*))) {
+      AssertMethod(&method);
+      EXPECT_FALSE(method.IsDirect());
+      EXPECT_TRUE(method.GetDeclaringClass()->IsAssignableFrom(klass.Get()));
     }
 
     for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
@@ -358,9 +356,10 @@
     class_linker_->VisitRoots(&visitor, kVisitRootFlagAllRoots);
     // Verify the dex cache has resolution methods in all resolved method slots
     mirror::DexCache* dex_cache = class_linker_->FindDexCache(dex);
-    mirror::ObjectArray<mirror::ArtMethod>* resolved_methods = dex_cache->GetResolvedMethods();
+    auto* resolved_methods = dex_cache->GetResolvedMethods();
     for (size_t i = 0; i < static_cast<size_t>(resolved_methods->GetLength()); i++) {
-      EXPECT_TRUE(resolved_methods->Get(i) != nullptr) << dex.GetLocation() << " i=" << i;
+      EXPECT_TRUE(resolved_methods->GetElementPtrSize<ArtMethod*>(i, sizeof(void*)) != nullptr)
+          << dex.GetLocation() << " i=" << i;
     }
   }
 
@@ -394,9 +393,8 @@
 
     bool error = false;
 
-    // Methods and classes have a different size due to padding field. Strings are variable length.
-    if (!klass->IsArtMethodClass() && !klass->IsClassClass() && !klass->IsStringClass() &&
-        !is_static) {
+    // Classes have a different size due to padding field. Strings are variable length.
+    if (!klass->IsClassClass() && !klass->IsStringClass() && !is_static) {
       // Currently only required for AccessibleObject since of the padding fields. The class linker
       // says AccessibleObject is 9 bytes but sizeof(AccessibleObject) is 12 bytes due to padding.
       // The RoundUp is to get around this case.
@@ -487,20 +485,6 @@
   };
 };
 
-struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> {
-  ArtMethodOffsets() : CheckOffsets<mirror::ArtMethod>(false, "Ljava/lang/reflect/ArtMethod;") {
-    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags");
-    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, declaring_class_), "declaringClass");
-    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_methods_),
-              "dexCacheResolvedMethods");
-    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_types_),
-              "dexCacheResolvedTypes");
-    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_), "dexCodeItemOffset");
-    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_), "dexMethodIndex");
-    addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_index_), "methodIndex");
-  };
-};
-
 struct ClassOffsets : public CheckOffsets<mirror::Class> {
   ClassOffsets() : CheckOffsets<mirror::Class>(false, "Ljava/lang/Class;") {
     addOffset(OFFSETOF_MEMBER(mirror::Class, access_flags_), "accessFlags");
@@ -516,12 +500,14 @@
     addOffset(OFFSETOF_MEMBER(mirror::Class, ifields_), "iFields");
     addOffset(OFFSETOF_MEMBER(mirror::Class, iftable_), "ifTable");
     addOffset(OFFSETOF_MEMBER(mirror::Class, name_), "name");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, num_direct_methods_), "numDirectMethods");
     addOffset(OFFSETOF_MEMBER(mirror::Class, num_instance_fields_), "numInstanceFields");
     addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_),
               "numReferenceInstanceFields");
     addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_static_fields_),
               "numReferenceStaticFields");
     addOffset(OFFSETOF_MEMBER(mirror::Class, num_static_fields_), "numStaticFields");
+    addOffset(OFFSETOF_MEMBER(mirror::Class, num_virtual_methods_), "numVirtualMethods");
     addOffset(OFFSETOF_MEMBER(mirror::Class, object_size_), "objectSize");
     addOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_), "primitiveType");
     addOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_),
@@ -641,7 +627,6 @@
 TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) {
   ScopedObjectAccess soa(Thread::Current());
   EXPECT_TRUE(ObjectOffsets().Check());
-  EXPECT_TRUE(ArtMethodOffsets().Check());
   EXPECT_TRUE(ClassOffsets().Check());
   EXPECT_TRUE(StringOffsets().Check());
   EXPECT_TRUE(ThrowableOffsets().Check());
@@ -899,7 +884,7 @@
   // Static final primitives that are initialized by a compile-time constant
   // expression resolve to a copy of a constant value from the constant pool.
   // So <clinit> should be null.
-  mirror::ArtMethod* clinit = statics->FindDirectMethod("<clinit>", "()V");
+  ArtMethod* clinit = statics->FindDirectMethod("<clinit>", "()V", sizeof(void*));
   EXPECT_TRUE(clinit == nullptr);
 
   EXPECT_EQ(9U, statics->NumStaticFields());
@@ -986,15 +971,15 @@
   EXPECT_TRUE(J->IsAssignableFrom(B.Get()));
 
   const Signature void_sig = I->GetDexCache()->GetDexFile()->CreateSignature("()V");
-  mirror::ArtMethod* Ii = I->FindVirtualMethod("i", void_sig);
-  mirror::ArtMethod* Jj1 = J->FindVirtualMethod("j1", void_sig);
-  mirror::ArtMethod* Jj2 = J->FindVirtualMethod("j2", void_sig);
-  mirror::ArtMethod* Kj1 = K->FindInterfaceMethod("j1", void_sig);
-  mirror::ArtMethod* Kj2 = K->FindInterfaceMethod("j2", void_sig);
-  mirror::ArtMethod* Kk = K->FindInterfaceMethod("k", void_sig);
-  mirror::ArtMethod* Ai = A->FindVirtualMethod("i", void_sig);
-  mirror::ArtMethod* Aj1 = A->FindVirtualMethod("j1", void_sig);
-  mirror::ArtMethod* Aj2 = A->FindVirtualMethod("j2", void_sig);
+  ArtMethod* Ii = I->FindVirtualMethod("i", void_sig, sizeof(void*));
+  ArtMethod* Jj1 = J->FindVirtualMethod("j1", void_sig, sizeof(void*));
+  ArtMethod* Jj2 = J->FindVirtualMethod("j2", void_sig, sizeof(void*));
+  ArtMethod* Kj1 = K->FindInterfaceMethod("j1", void_sig, sizeof(void*));
+  ArtMethod* Kj2 = K->FindInterfaceMethod("j2", void_sig, sizeof(void*));
+  ArtMethod* Kk = K->FindInterfaceMethod("k", void_sig, sizeof(void*));
+  ArtMethod* Ai = A->FindVirtualMethod("i", void_sig, sizeof(void*));
+  ArtMethod* Aj1 = A->FindVirtualMethod("j1", void_sig, sizeof(void*));
+  ArtMethod* Aj2 = A->FindVirtualMethod("j2", void_sig, sizeof(void*));
   ASSERT_TRUE(Ii != nullptr);
   ASSERT_TRUE(Jj1 != nullptr);
   ASSERT_TRUE(Jj2 != nullptr);
@@ -1009,21 +994,17 @@
   EXPECT_NE(Jj2, Aj2);
   EXPECT_EQ(Kj1, Jj1);
   EXPECT_EQ(Kj2, Jj2);
-  EXPECT_EQ(Ai, A->FindVirtualMethodForInterface(Ii));
-  EXPECT_EQ(Aj1, A->FindVirtualMethodForInterface(Jj1));
-  EXPECT_EQ(Aj2, A->FindVirtualMethodForInterface(Jj2));
-  EXPECT_EQ(Ai, A->FindVirtualMethodForVirtualOrInterface(Ii));
-  EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1));
-  EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2));
+  EXPECT_EQ(Ai, A->FindVirtualMethodForInterface(Ii, sizeof(void*)));
+  EXPECT_EQ(Aj1, A->FindVirtualMethodForInterface(Jj1, sizeof(void*)));
+  EXPECT_EQ(Aj2, A->FindVirtualMethodForInterface(Jj2, sizeof(void*)));
+  EXPECT_EQ(Ai, A->FindVirtualMethodForVirtualOrInterface(Ii, sizeof(void*)));
+  EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1, sizeof(void*)));
+  EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2, sizeof(void*)));
 
-  ArtField* Afoo = mirror::Class::FindStaticField(soa.Self(), A, "foo",
-                                                          "Ljava/lang/String;");
-  ArtField* Bfoo = mirror::Class::FindStaticField(soa.Self(), B, "foo",
-                                                          "Ljava/lang/String;");
-  ArtField* Jfoo = mirror::Class::FindStaticField(soa.Self(), J, "foo",
-                                                          "Ljava/lang/String;");
-  ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo",
-                                                          "Ljava/lang/String;");
+  ArtField* Afoo = mirror::Class::FindStaticField(soa.Self(), A, "foo", "Ljava/lang/String;");
+  ArtField* Bfoo = mirror::Class::FindStaticField(soa.Self(), B, "foo", "Ljava/lang/String;");
+  ArtField* Jfoo = mirror::Class::FindStaticField(soa.Self(), J, "foo", "Ljava/lang/String;");
+  ArtField* Kfoo = mirror::Class::FindStaticField(soa.Self(), K, "foo", "Ljava/lang/String;");
   ASSERT_TRUE(Afoo != nullptr);
   EXPECT_EQ(Afoo, Bfoo);
   EXPECT_EQ(Afoo, Jfoo);
@@ -1043,17 +1024,17 @@
   Handle<mirror::ClassLoader> class_loader(
       hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
   mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", class_loader);
-  mirror::ArtMethod* clinit = klass->FindClassInitializer();
-  mirror::ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;");
+  ArtMethod* clinit = klass->FindClassInitializer(sizeof(void*));
+  ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;", sizeof(void*));
   const DexFile::StringId* string_id = dex_file->FindStringId("LStaticsFromCode;");
   ASSERT_TRUE(string_id != nullptr);
   const DexFile::TypeId* type_id = dex_file->FindTypeId(dex_file->GetIndexForStringId(*string_id));
   ASSERT_TRUE(type_id != nullptr);
   uint32_t type_idx = dex_file->GetIndexForTypeId(*type_id);
-  mirror::Class* uninit = ResolveVerifyAndClinit(type_idx, clinit, Thread::Current(), true, false);
+  mirror::Class* uninit = ResolveVerifyAndClinit(type_idx, clinit, soa.Self(), true, false);
   EXPECT_TRUE(uninit != nullptr);
   EXPECT_FALSE(uninit->IsInitialized());
-  mirror::Class* init = ResolveVerifyAndClinit(type_idx, getS0, Thread::Current(), true, false);
+  mirror::Class* init = ResolveVerifyAndClinit(type_idx, getS0, soa.Self(), true, false);
   EXPECT_TRUE(init != nullptr);
   EXPECT_TRUE(init->IsInitialized());
 }
@@ -1109,22 +1090,23 @@
   mirror::Class* c;
 
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Class;", class_loader);
-  EXPECT_EQ(c->GetClassSize(), mirror::Class::ClassClassSize());
+  ASSERT_TRUE(c != nullptr);
+  EXPECT_EQ(c->GetClassSize(), mirror::Class::ClassClassSize(sizeof(void*)));
 
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Object;", class_loader);
-  EXPECT_EQ(c->GetClassSize(), mirror::Object::ClassSize());
+  ASSERT_TRUE(c != nullptr);
+  EXPECT_EQ(c->GetClassSize(), mirror::Object::ClassSize(sizeof(void*)));
 
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/String;", class_loader);
-  EXPECT_EQ(c->GetClassSize(), mirror::String::ClassSize());
+  ASSERT_TRUE(c != nullptr);
+  EXPECT_EQ(c->GetClassSize(), mirror::String::ClassSize(sizeof(void*)));
 
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/DexCache;", class_loader);
-  EXPECT_EQ(c->GetClassSize(), mirror::DexCache::ClassSize());
-
-  c = class_linker_->FindClass(soa.Self(), "Ljava/lang/reflect/ArtMethod;", class_loader);
-  EXPECT_EQ(c->GetClassSize(), mirror::ArtMethod::ClassSize());
+  ASSERT_TRUE(c != nullptr);
+  EXPECT_EQ(c->GetClassSize(), mirror::DexCache::ClassSize(sizeof(void*)));
 }
 
-static void CheckMethod(mirror::ArtMethod* method, bool verified)
+static void CheckMethod(ArtMethod* method, bool verified)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (!method->IsNative() && !method->IsAbstract()) {
     EXPECT_EQ((method->GetAccessFlags() & kAccPreverified) != 0U, verified)
@@ -1136,11 +1118,11 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   EXPECT_EQ((c->GetAccessFlags() & kAccPreverified) != 0U, preverified)
       << "Class " << PrettyClass(c) << " not as expected";
-  for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) {
-    CheckMethod(c->GetDirectMethod(i), preverified);
+  for (auto& m : c->GetDirectMethods(sizeof(void*))) {
+    CheckMethod(&m, preverified);
   }
-  for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) {
-    CheckMethod(c->GetVirtualMethod(i), preverified);
+  for (auto& m : c->GetVirtualMethods(sizeof(void*))) {
+    CheckMethod(&m, preverified);
   }
 }
 
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index de3a29b..5f9e413 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 
 #include "../../external/icu/icu4c/source/common/unicode/uvernum.h"
+#include "art_field-inl.h"
 #include "base/macros.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
@@ -31,17 +32,19 @@
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
 #include "compiler_callbacks.h"
-#include "dex_file.h"
+#include "dex_file-inl.h"
 #include "gc_root-inl.h"
 #include "gc/heap.h"
 #include "gtest/gtest.h"
 #include "handle_scope-inl.h"
 #include "interpreter/unstarted_runtime.h"
 #include "jni_internal.h"
+#include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mem_map.h"
 #include "noop_compiler_callbacks.h"
 #include "os.h"
+#include "primitive.h"
 #include "runtime-inl.h"
 #include "scoped_thread_state_change.h"
 #include "thread.h"
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index fb81ad2..3acd366 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -19,12 +19,12 @@
 #include <sstream>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
 #include "dex_instruction-inl.h"
 #include "invoke_type.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
@@ -78,7 +78,7 @@
 
 // AbstractMethodError
 
-void ThrowAbstractMethodError(mirror::ArtMethod* method) {
+void ThrowAbstractMethodError(ArtMethod* method) {
   ThrowException("Ljava/lang/AbstractMethodError;", nullptr,
                  StringPrintf("abstract method \"%s\"",
                               PrettyMethod(method).c_str()).c_str());
@@ -145,7 +145,7 @@
 }
 
 void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
-                                                   mirror::ArtMethod* called,
+                                                   ArtMethod* called,
                                                    InvokeType type) {
   std::ostringstream msg;
   msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '"
@@ -154,7 +154,7 @@
   ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
 }
 
-void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed) {
+void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, ArtMethod* accessed) {
   std::ostringstream msg;
   msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '"
       << PrettyDescriptor(referrer) << "'";
@@ -168,13 +168,12 @@
   ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
 }
 
-void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer,
-                                       ArtField* accessed) {
+void ThrowIllegalAccessErrorFinalField(ArtMethod* referrer, ArtField* accessed) {
   std::ostringstream msg;
   msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
       << PrettyMethod(referrer) << "'";
   ThrowException("Ljava/lang/IllegalAccessError;",
-                 referrer != nullptr ? referrer->GetClass() : nullptr,
+                 referrer != nullptr ? referrer->GetDeclaringClass() : nullptr,
                  msg.str().c_str());
 }
 
@@ -201,19 +200,18 @@
 // IncompatibleClassChangeError
 
 void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
-                                       mirror::ArtMethod* method,
-                                       mirror::ArtMethod* referrer) {
+                                       ArtMethod* method, ArtMethod* referrer) {
   std::ostringstream msg;
   msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
       << expected_type << " but instead was found to be of type " << found_type;
   ThrowException("Ljava/lang/IncompatibleClassChangeError;",
-                 referrer != nullptr ? referrer->GetClass() : nullptr,
+                 referrer != nullptr ? referrer->GetDeclaringClass() : nullptr,
                  msg.str().c_str());
 }
 
-void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method,
+void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(ArtMethod* interface_method,
                                                                 mirror::Object* this_object,
-                                                                mirror::ArtMethod* referrer) {
+                                                                ArtMethod* referrer) {
   // Referrer is calling interface_method on this_object, however, the interface_method isn't
   // implemented by this_object.
   CHECK(this_object != nullptr);
@@ -223,17 +221,17 @@
       << PrettyDescriptor(interface_method->GetDeclaringClass())
       << "' in call to '" << PrettyMethod(interface_method) << "'";
   ThrowException("Ljava/lang/IncompatibleClassChangeError;",
-                 referrer != nullptr ? referrer->GetClass() : nullptr,
+                 referrer != nullptr ? referrer->GetDeclaringClass() : nullptr,
                  msg.str().c_str());
 }
 
 void ThrowIncompatibleClassChangeErrorField(ArtField* resolved_field, bool is_static,
-                                            mirror::ArtMethod* referrer) {
+                                            ArtMethod* referrer) {
   std::ostringstream msg;
   msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
       << (is_static ? "static" : "instance") << " field" << " rather than a "
       << (is_static ? "instance" : "static") << " field";
-  ThrowException("Ljava/lang/IncompatibleClassChangeError;", referrer->GetClass(),
+  ThrowException("Ljava/lang/IncompatibleClassChangeError;", referrer->GetDeclaringClass(),
                  msg.str().c_str());
 }
 
@@ -317,7 +315,7 @@
 }
 
 void ThrowNoSuchMethodError(uint32_t method_idx) {
-  mirror::ArtMethod* method = Thread::Current()->GetCurrentMethod(nullptr);
+  ArtMethod* method = Thread::Current()->GetCurrentMethod(nullptr);
   mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
   const DexFile& dex_file = *dex_cache->GetDexFile();
   std::ostringstream msg;
@@ -353,7 +351,7 @@
   ThrowNullPointerExceptionForMethodAccessImpl(method_idx, dex_file, type);
 }
 
-void ThrowNullPointerExceptionForMethodAccess(mirror::ArtMethod* method,
+void ThrowNullPointerExceptionForMethodAccess(ArtMethod* method,
                                               InvokeType type) {
   mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
   const DexFile& dex_file = *dex_cache->GetDexFile();
@@ -363,7 +361,7 @@
 
 void ThrowNullPointerExceptionFromDexPC() {
   uint32_t throw_dex_pc;
-  mirror::ArtMethod* method = Thread::Current()->GetCurrentMethod(&throw_dex_pc);
+  ArtMethod* method = Thread::Current()->GetCurrentMethod(&throw_dex_pc);
   const DexFile::CodeItem* code = method->GetCodeItem();
   CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_);
   const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]);
@@ -390,7 +388,7 @@
     case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
       // Since we replaced the method index, we ask the verifier to tell us which
       // method is invoked at this location.
-      mirror::ArtMethod* invoked_method =
+      ArtMethod* invoked_method =
           verifier::MethodVerifier::FindInvokedMethodAtDexPc(method, throw_dex_pc);
       if (invoked_method != nullptr) {
         // NPE with precise message.
diff --git a/runtime/common_throws.h b/runtime/common_throws.h
index bd667fa..b391c5b 100644
--- a/runtime/common_throws.h
+++ b/runtime/common_throws.h
@@ -22,17 +22,17 @@
 
 namespace art {
 namespace mirror {
-  class ArtMethod;
   class Class;
   class Object;
 }  // namespace mirror
 class ArtField;
+class ArtMethod;
 class Signature;
 class StringPiece;
 
 // AbstractMethodError
 
-void ThrowAbstractMethodError(mirror::ArtMethod* method)
+void ThrowAbstractMethodError(ArtMethod* method)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
 // ArithmeticException
@@ -74,17 +74,17 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
 void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
-                                                   mirror::ArtMethod* called,
+                                                   ArtMethod* called,
                                                    InvokeType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
-void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed)
+void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, ArtMethod* accessed)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
 void ThrowIllegalAccessErrorField(mirror::Class* referrer, ArtField* accessed)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
-void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer, ArtField* accessed)
+void ThrowIllegalAccessErrorFinalField(ArtMethod* referrer, ArtField* accessed)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
 void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...)
@@ -104,16 +104,16 @@
 // IncompatibleClassChangeError
 
 void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
-                                       mirror::ArtMethod* method, mirror::ArtMethod* referrer)
+                                       ArtMethod* method, ArtMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
-void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method,
+void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(ArtMethod* interface_method,
                                                                 mirror::Object* this_object,
-                                                                mirror::ArtMethod* referrer)
+                                                                ArtMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
 void ThrowIncompatibleClassChangeErrorField(ArtField* resolved_field, bool is_static,
-                                            mirror::ArtMethod* referrer)
+                                            ArtMethod* referrer)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
 void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...)
@@ -175,7 +175,7 @@
                                               InvokeType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
-void ThrowNullPointerExceptionForMethodAccess(mirror::ArtMethod* method,
+void ThrowNullPointerExceptionForMethodAccess(ArtMethod* method,
                                               InvokeType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 728e8e3..7999559 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -22,6 +22,7 @@
 
 #include "arch/context.h"
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/time_utils.h"
 #include "class_linker.h"
 #include "class_linker-inl.h"
@@ -32,7 +33,6 @@
 #include "gc/space/space-inl.h"
 #include "handle_scope.h"
 #include "jdwp/object_registry.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
@@ -78,17 +78,17 @@
   }
 
   int32_t LineNumber() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* method = Method();
+    ArtMethod* method = Method();
     DCHECK(method != nullptr);
     return method->GetLineNumFromDexPC(DexPc());
   }
 
-  mirror::ArtMethod* Method() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ArtMethod* Method() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     ScopedObjectAccessUnchecked soa(Thread::Current());
     return soa.DecodeMethod(method_);
   }
 
-  void SetMethod(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void SetMethod(ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     ScopedObjectAccessUnchecked soa(Thread::Current());
     method_ = soa.EncodeMethod(m);
   }
@@ -184,7 +184,7 @@
 
 class Breakpoint {
  public:
-  Breakpoint(mirror::ArtMethod* method, uint32_t dex_pc,
+  Breakpoint(ArtMethod* method, uint32_t dex_pc,
              DeoptimizationRequest::Kind deoptimization_kind)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
     : method_(nullptr), dex_pc_(dex_pc), deoptimization_kind_(deoptimization_kind) {
@@ -202,7 +202,7 @@
     method_ = soa.EncodeMethod(other.Method());
   }
 
-  mirror::ArtMethod* Method() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ArtMethod* Method() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     ScopedObjectAccessUnchecked soa(Thread::Current());
     return soa.DecodeMethod(method_);
   }
@@ -235,7 +235,7 @@
   DebugInstrumentationListener() {}
   virtual ~DebugInstrumentationListener() {}
 
-  void MethodEntered(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method,
+  void MethodEntered(Thread* thread, mirror::Object* this_object, ArtMethod* method,
                      uint32_t dex_pc)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (method->IsNative()) {
@@ -261,7 +261,7 @@
     }
   }
 
-  void MethodExited(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method,
+  void MethodExited(Thread* thread, mirror::Object* this_object, ArtMethod* method,
                     uint32_t dex_pc, const JValue& return_value)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (method->IsNative()) {
@@ -279,14 +279,14 @@
   }
 
   void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object ATTRIBUTE_UNUSED,
-                    mirror::ArtMethod* method, uint32_t dex_pc)
+                    ArtMethod* method, uint32_t dex_pc)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // We're not recorded to listen to this kind of event, so complain.
     LOG(ERROR) << "Unexpected method unwind event in debugger " << PrettyMethod(method)
                << " " << dex_pc;
   }
 
-  void DexPcMoved(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method,
+  void DexPcMoved(Thread* thread, mirror::Object* this_object, ArtMethod* method,
                   uint32_t new_dex_pc)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (IsListeningToMethodExit() && IsReturn(method, new_dex_pc)) {
@@ -308,13 +308,13 @@
   }
 
   void FieldRead(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object,
-                 mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field)
+                 ArtMethod* method, uint32_t dex_pc, ArtField* field)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Dbg::PostFieldAccessEvent(method, dex_pc, this_object, field);
   }
 
   void FieldWritten(Thread* thread ATTRIBUTE_UNUSED, mirror::Object* this_object,
-                    mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field,
+                    ArtMethod* method, uint32_t dex_pc, ArtField* field,
                     const JValue& field_value)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Dbg::PostFieldModificationEvent(method, dex_pc, this_object, field, &field_value);
@@ -326,14 +326,14 @@
   }
 
   // We only care about how many backward branches were executed in the Jit.
-  void BackwardBranch(Thread* /*thread*/, mirror::ArtMethod* method, int32_t dex_pc_offset)
+  void BackwardBranch(Thread* /*thread*/, ArtMethod* method, int32_t dex_pc_offset)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     LOG(ERROR) << "Unexpected backward branch event in debugger " << PrettyMethod(method)
                << " " << dex_pc_offset;
   }
 
  private:
-  static bool IsReturn(mirror::ArtMethod* method, uint32_t dex_pc)
+  static bool IsReturn(ArtMethod* method, uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const DexFile::CodeItem* code_item = method->GetCodeItem();
     const Instruction* instruction = Instruction::At(&code_item->insns_[dex_pc]);
@@ -408,11 +408,6 @@
 void DebugInvokeReq::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) {
   receiver.VisitRootIfNonNull(visitor, root_info);  // null for static method call.
   klass.VisitRoot(visitor, root_info);
-  method.VisitRoot(visitor, root_info);
-}
-
-void SingleStepControl::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) {
-  method_.VisitRootIfNonNull(visitor, root_info);
 }
 
 void SingleStepControl::AddDexPc(uint32_t dex_pc) {
@@ -423,7 +418,7 @@
   return dex_pcs_.find(dex_pc) == dex_pcs_.end();
 }
 
-static bool IsBreakpoint(const mirror::ArtMethod* m, uint32_t dex_pc)
+static bool IsBreakpoint(const ArtMethod* m, uint32_t dex_pc)
     LOCKS_EXCLUDED(Locks::breakpoint_lock_)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
@@ -1395,9 +1390,8 @@
   return static_cast<JDWP::FieldId>(reinterpret_cast<uintptr_t>(f));
 }
 
-static JDWP::MethodId ToMethodId(const mirror::ArtMethod* m)
+static JDWP::MethodId ToMethodId(const ArtMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  CHECK(!kMovingMethods);
   return static_cast<JDWP::MethodId>(reinterpret_cast<uintptr_t>(m));
 }
 
@@ -1406,17 +1400,16 @@
   return reinterpret_cast<ArtField*>(static_cast<uintptr_t>(fid));
 }
 
-static mirror::ArtMethod* FromMethodId(JDWP::MethodId mid)
+static ArtMethod* FromMethodId(JDWP::MethodId mid)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  CHECK(!kMovingMethods);
-  return reinterpret_cast<mirror::ArtMethod*>(static_cast<uintptr_t>(mid));
+  return reinterpret_cast<ArtMethod*>(static_cast<uintptr_t>(mid));
 }
 
 bool Dbg::MatchThread(JDWP::ObjectId expected_thread_id, Thread* event_thread) {
   CHECK(event_thread != nullptr);
   JDWP::JdwpError error;
-  mirror::Object* expected_thread_peer = gRegistry->Get<mirror::Object*>(expected_thread_id,
-                                                                         &error);
+  mirror::Object* expected_thread_peer = gRegistry->Get<mirror::Object*>(
+      expected_thread_id, &error);
   return expected_thread_peer == event_thread->GetPeer();
 }
 
@@ -1425,7 +1418,7 @@
   if (expected_location.dex_pc != event_location.dex_pc) {
     return false;
   }
-  mirror::ArtMethod* m = FromMethodId(expected_location.method_id);
+  ArtMethod* m = FromMethodId(expected_location.method_id);
   return m == event_location.method;
 }
 
@@ -1454,7 +1447,7 @@
   return modifier_instance == event_instance;
 }
 
-void Dbg::SetJdwpLocation(JDWP::JdwpLocation* location, mirror::ArtMethod* m, uint32_t dex_pc)
+void Dbg::SetJdwpLocation(JDWP::JdwpLocation* location, ArtMethod* m, uint32_t dex_pc)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
     LOCKS_EXCLUDED(Locks::thread_list_lock_,
                    Locks::thread_suspend_count_lock_) {
@@ -1470,7 +1463,7 @@
 }
 
 std::string Dbg::GetMethodName(JDWP::MethodId method_id) {
-  mirror::ArtMethod* m = FromMethodId(method_id);
+  ArtMethod* m = FromMethodId(method_id);
   if (m == nullptr) {
     return "null";
   }
@@ -1503,7 +1496,7 @@
  * expect slots to begin with arguments, but dex code places them at
  * the end.
  */
-static uint16_t MangleSlot(uint16_t slot, mirror::ArtMethod* m)
+static uint16_t MangleSlot(uint16_t slot, ArtMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   const DexFile::CodeItem* code_item = m->GetCodeItem();
   if (code_item == nullptr) {
@@ -1525,14 +1518,14 @@
  * Circularly shifts registers so that arguments come last. Reverts
  * slots to dex style argument placement.
  */
-static uint16_t DemangleSlot(uint16_t slot, mirror::ArtMethod* m, JDWP::JdwpError* error)
+static uint16_t DemangleSlot(uint16_t slot, ArtMethod* m, JDWP::JdwpError* error)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   const DexFile::CodeItem* code_item = m->GetCodeItem();
   if (code_item == nullptr) {
     // We should not get here for a method without code (native, proxy or abstract). Log it and
     // return the slot as is since all registers are arguments.
     LOG(WARNING) << "Trying to demangle slot for method without code " << PrettyMethod(m);
-    uint16_t vreg_count = mirror::ArtMethod::NumArgRegisters(m->GetShorty());
+    uint16_t vreg_count = ArtMethod::NumArgRegisters(m->GetShorty());
     if (slot < vreg_count) {
       *error = JDWP::ERR_NONE;
       return slot;
@@ -1591,14 +1584,17 @@
 
   expandBufAdd4BE(pReply, direct_method_count + virtual_method_count);
 
+  auto* cl = Runtime::Current()->GetClassLinker();
+  auto ptr_size = cl->GetImagePointerSize();
   for (size_t i = 0; i < direct_method_count + virtual_method_count; ++i) {
-    mirror::ArtMethod* m = (i < direct_method_count) ? c->GetDirectMethod(i) : c->GetVirtualMethod(i - direct_method_count);
+    ArtMethod* m = i < direct_method_count ?
+        c->GetDirectMethod(i, ptr_size) : c->GetVirtualMethod(i - direct_method_count, ptr_size);
     expandBufAddMethodId(pReply, ToMethodId(m));
     expandBufAddUtf8String(pReply, m->GetName());
     expandBufAddUtf8String(pReply, m->GetSignature().ToString());
     if (with_generic) {
-      static const char genericSignature[1] = "";
-      expandBufAddUtf8String(pReply, genericSignature);
+      const char* generic_signature = "";
+      expandBufAddUtf8String(pReply, generic_signature);
     }
     expandBufAdd4BE(pReply, MangleAccessFlags(m->GetAccessFlags()));
   }
@@ -1635,7 +1631,7 @@
       return false;
     }
   };
-  mirror::ArtMethod* m = FromMethodId(method_id);
+  ArtMethod* m = FromMethodId(method_id);
   const DexFile::CodeItem* code_item = m->GetCodeItem();
   uint64_t start, end;
   if (code_item == nullptr) {
@@ -1670,7 +1666,7 @@
 void Dbg::OutputVariableTable(JDWP::RefTypeId, JDWP::MethodId method_id, bool with_generic,
                               JDWP::ExpandBuf* pReply) {
   struct DebugCallbackContext {
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     JDWP::ExpandBuf* pReply;
     size_t variable_count;
     bool with_generic;
@@ -1699,12 +1695,12 @@
       ++pContext->variable_count;
     }
   };
-  mirror::ArtMethod* m = FromMethodId(method_id);
+  ArtMethod* m = FromMethodId(method_id);
 
   // arg_count considers doubles and longs to take 2 units.
   // variable_count considers everything to take 1 unit.
   std::string shorty(m->GetShorty());
-  expandBufAdd4BE(pReply, mirror::ArtMethod::NumArgRegisters(shorty));
+  expandBufAdd4BE(pReply, ArtMethod::NumArgRegisters(shorty));
 
   // We don't know the total number of variables yet, so leave a blank and update it later.
   size_t variable_count_offset = expandBufGetLength(pReply);
@@ -1728,7 +1724,7 @@
 
 void Dbg::OutputMethodReturnValue(JDWP::MethodId method_id, const JValue* return_value,
                                   JDWP::ExpandBuf* pReply) {
-  mirror::ArtMethod* m = FromMethodId(method_id);
+  ArtMethod* m = FromMethodId(method_id);
   JDWP::JdwpTag tag = BasicTagFromDescriptor(m->GetShorty());
   OutputJValue(tag, return_value, pReply);
 }
@@ -1742,7 +1738,7 @@
 
 JDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id,
                                   std::vector<uint8_t>* bytecodes) {
-  mirror::ArtMethod* m = FromMethodId(method_id);
+  ArtMethod* m = FromMethodId(method_id);
   if (m == nullptr) {
     return JDWP::ERR_INVALID_METHODID;
   }
@@ -2470,7 +2466,7 @@
     if (GetFrameId() != frame_id_) {
       return true;  // Not our frame, carry on.
     }
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     if (m->IsNative()) {
       // We can't read/write local value from/into native method.
       error_ = JDWP::ERR_OPAQUE_FRAME;
@@ -2548,7 +2544,7 @@
 
 JDWP::JdwpError Dbg::GetLocalValue(const StackVisitor& visitor, ScopedObjectAccessUnchecked& soa,
                                    int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t width) {
-  mirror::ArtMethod* m = visitor.GetMethod();
+  ArtMethod* m = visitor.GetMethod();
   JDWP::JdwpError error = JDWP::ERR_NONE;
   uint16_t vreg = DemangleSlot(slot, m, &error);
   if (error != JDWP::ERR_NONE) {
@@ -2711,7 +2707,7 @@
 
 JDWP::JdwpError Dbg::SetLocalValue(StackVisitor& visitor, int slot, JDWP::JdwpTag tag,
                                    uint64_t value, size_t width) {
-  mirror::ArtMethod* m = visitor.GetMethod();
+  ArtMethod* m = visitor.GetMethod();
   JDWP::JdwpError error = JDWP::ERR_NONE;
   uint16_t vreg = DemangleSlot(slot, m, &error);
   if (error != JDWP::ERR_NONE) {
@@ -2786,7 +2782,7 @@
   return JDWP::ERR_NONE;
 }
 
-static void SetEventLocation(JDWP::EventLocation* location, mirror::ArtMethod* m, uint32_t dex_pc)
+static void SetEventLocation(JDWP::EventLocation* location, ArtMethod* m, uint32_t dex_pc)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(location != nullptr);
   if (m == nullptr) {
@@ -2797,7 +2793,7 @@
   }
 }
 
-void Dbg::PostLocationEvent(mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object,
+void Dbg::PostLocationEvent(ArtMethod* m, int dex_pc, mirror::Object* this_object,
                             int event_flags, const JValue* return_value) {
   if (!IsDebuggerActive()) {
     return;
@@ -2830,7 +2826,7 @@
   }
 }
 
-void Dbg::PostFieldAccessEvent(mirror::ArtMethod* m, int dex_pc,
+void Dbg::PostFieldAccessEvent(ArtMethod* m, int dex_pc,
                                mirror::Object* this_object, ArtField* f) {
   if (!IsDebuggerActive()) {
     return;
@@ -2843,7 +2839,7 @@
   gJdwpState->PostFieldEvent(&location, f, this_object, nullptr, false);
 }
 
-void Dbg::PostFieldModificationEvent(mirror::ArtMethod* m, int dex_pc,
+void Dbg::PostFieldModificationEvent(ArtMethod* m, int dex_pc,
                                      mirror::Object* this_object, ArtField* f,
                                      const JValue* field_value) {
   if (!IsDebuggerActive()) {
@@ -2871,14 +2867,14 @@
       exception_(exception),
       handle_scope_(self),
       this_at_throw_(handle_scope_.NewHandle<mirror::Object>(nullptr)),
-      catch_method_(handle_scope_.NewHandle<mirror::ArtMethod>(nullptr)),
-      throw_method_(handle_scope_.NewHandle<mirror::ArtMethod>(nullptr)),
+      catch_method_(nullptr),
+      throw_method_(nullptr),
       catch_dex_pc_(DexFile::kDexNoIndex),
       throw_dex_pc_(DexFile::kDexNoIndex) {
   }
 
   bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* method = GetMethod();
+    ArtMethod* method = GetMethod();
     DCHECK(method != nullptr);
     if (method->IsRuntimeMethod()) {
       // Ignore callee save method.
@@ -2887,25 +2883,23 @@
     }
 
     uint32_t dex_pc = GetDexPc();
-    if (throw_method_.Get() == nullptr) {
+    if (throw_method_ == nullptr) {
       // First Java method found. It is either the method that threw the exception,
       // or the Java native method that is reporting an exception thrown by
       // native code.
       this_at_throw_.Assign(GetThisObject());
-      throw_method_.Assign(method);
+      throw_method_ = method;
       throw_dex_pc_ = dex_pc;
     }
 
     if (dex_pc != DexFile::kDexNoIndex) {
-      StackHandleScope<2> hs(self_);
+      StackHandleScope<1> hs(self_);
       uint32_t found_dex_pc;
       Handle<mirror::Class> exception_class(hs.NewHandle(exception_->GetClass()));
-      Handle<mirror::ArtMethod> h_method(hs.NewHandle(method));
       bool unused_clear_exception;
-      found_dex_pc = mirror::ArtMethod::FindCatchBlock(
-          h_method, exception_class, dex_pc, &unused_clear_exception);
+      found_dex_pc = method->FindCatchBlock(exception_class, dex_pc, &unused_clear_exception);
       if (found_dex_pc != DexFile::kDexNoIndex) {
-        catch_method_.Assign(method);
+        catch_method_ = method;
         catch_dex_pc_ = found_dex_pc;
         return false;  // End stack walk.
       }
@@ -2913,12 +2907,12 @@
     return true;  // Continue stack walk.
   }
 
-  mirror::ArtMethod* GetCatchMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return catch_method_.Get();
+  ArtMethod* GetCatchMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return catch_method_;
   }
 
-  mirror::ArtMethod* GetThrowMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return throw_method_.Get();
+  ArtMethod* GetThrowMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return throw_method_;
   }
 
   mirror::Object* GetThisAtThrow() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -2936,10 +2930,10 @@
  private:
   Thread* const self_;
   const Handle<mirror::Throwable>& exception_;
-  StackHandleScope<3> handle_scope_;
+  StackHandleScope<1> handle_scope_;
   MutableHandle<mirror::Object> this_at_throw_;
-  MutableHandle<mirror::ArtMethod> catch_method_;
-  MutableHandle<mirror::ArtMethod> throw_method_;
+  ArtMethod* catch_method_;
+  ArtMethod* throw_method_;
   uint32_t catch_dex_pc_;
   uint32_t throw_dex_pc_;
 
@@ -2973,7 +2967,7 @@
 }
 
 void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object,
-                         mirror::ArtMethod* m, uint32_t dex_pc,
+                         ArtMethod* m, uint32_t dex_pc,
                          int event_flags, const JValue* return_value) {
   if (!IsDebuggerActive() || dex_pc == static_cast<uint32_t>(-2) /* fake method exit */) {
     return;
@@ -3222,7 +3216,7 @@
   self->TransitionFromSuspendedToRunnable();
 }
 
-static bool IsMethodPossiblyInlined(Thread* self, mirror::ArtMethod* m)
+static bool IsMethodPossiblyInlined(Thread* self, ArtMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   const DexFile::CodeItem* code_item = m->GetCodeItem();
   if (code_item == nullptr) {
@@ -3232,19 +3226,18 @@
   }
   // Note: method verifier may cause thread suspension.
   self->AssertThreadSuspensionIsAllowable();
-  StackHandleScope<3> hs(self);
+  StackHandleScope<2> hs(self);
   mirror::Class* declaring_class = m->GetDeclaringClass();
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
-  Handle<mirror::ArtMethod> method(hs.NewHandle(m));
   verifier::MethodVerifier verifier(self, dex_cache->GetDexFile(), dex_cache, class_loader,
-                                    &m->GetClassDef(), code_item, m->GetDexMethodIndex(), method,
+                                    &m->GetClassDef(), code_item, m->GetDexMethodIndex(), m,
                                     m->GetAccessFlags(), false, true, false, true);
   // Note: we don't need to verify the method.
   return InlineMethodAnalyser::AnalyseMethodCode(&verifier, nullptr);
 }
 
-static const Breakpoint* FindFirstBreakpointForMethod(mirror::ArtMethod* m)
+static const Breakpoint* FindFirstBreakpointForMethod(ArtMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::breakpoint_lock_) {
   for (Breakpoint& breakpoint : gBreakpoints) {
     if (breakpoint.Method() == m) {
@@ -3254,13 +3247,13 @@
   return nullptr;
 }
 
-bool Dbg::MethodHasAnyBreakpoints(mirror::ArtMethod* method) {
+bool Dbg::MethodHasAnyBreakpoints(ArtMethod* method) {
   ReaderMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
   return FindFirstBreakpointForMethod(method) != nullptr;
 }
 
 // Sanity checks all existing breakpoints on the same method.
-static void SanityCheckExistingBreakpoints(mirror::ArtMethod* m,
+static void SanityCheckExistingBreakpoints(ArtMethod* m,
                                            DeoptimizationRequest::Kind deoptimization_kind)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::breakpoint_lock_) {
   for (const Breakpoint& breakpoint : gBreakpoints) {
@@ -3289,7 +3282,7 @@
 // If a breakpoint has already been set, we also return the first breakpoint
 // through the given 'existing_brkpt' pointer.
 static DeoptimizationRequest::Kind GetRequiredDeoptimizationKind(Thread* self,
-                                                                 mirror::ArtMethod* m,
+                                                                 ArtMethod* m,
                                                                  const Breakpoint** existing_brkpt)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (!Dbg::RequiresDeoptimization()) {
@@ -3353,7 +3346,7 @@
 // request if we need to deoptimize.
 void Dbg::WatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) {
   Thread* const self = Thread::Current();
-  mirror::ArtMethod* m = FromMethodId(location->method_id);
+  ArtMethod* m = FromMethodId(location->method_id);
   DCHECK(m != nullptr) << "No method for method id " << location->method_id;
 
   const Breakpoint* existing_breakpoint = nullptr;
@@ -3388,7 +3381,7 @@
 // request if we need to undeoptimize.
 void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location, DeoptimizationRequest* req) {
   WriterMutexLock mu(Thread::Current(), *Locks::breakpoint_lock_);
-  mirror::ArtMethod* m = FromMethodId(location->method_id);
+  ArtMethod* m = FromMethodId(location->method_id);
   DCHECK(m != nullptr) << "No method for method id " << location->method_id;
   DeoptimizationRequest::Kind deoptimization_kind = DeoptimizationRequest::kNothing;
   for (size_t i = 0, e = gBreakpoints.size(); i < e; ++i) {
@@ -3428,7 +3421,7 @@
   }
 }
 
-bool Dbg::IsForcedInterpreterNeededForCallingImpl(Thread* thread, mirror::ArtMethod* m) {
+bool Dbg::IsForcedInterpreterNeededForCallingImpl(Thread* thread, ArtMethod* m) {
   const SingleStepControl* const ssc = thread->GetSingleStepControl();
   if (ssc == nullptr) {
     // If we are not single-stepping, then we don't have to force interpreter.
@@ -3448,7 +3441,7 @@
   return false;
 }
 
-bool Dbg::IsForcedInterpreterNeededForResolutionImpl(Thread* thread, mirror::ArtMethod* m) {
+bool Dbg::IsForcedInterpreterNeededForResolutionImpl(Thread* thread, ArtMethod* m) {
   instrumentation::Instrumentation* const instrumentation =
       Runtime::Current()->GetInstrumentation();
   // If we are in interpreter only mode, then we don't have to force interpreter.
@@ -3482,7 +3475,7 @@
   return instrumentation->IsDeoptimized(m);
 }
 
-bool Dbg::IsForcedInstrumentationNeededForResolutionImpl(Thread* thread, mirror::ArtMethod* m) {
+bool Dbg::IsForcedInstrumentationNeededForResolutionImpl(Thread* thread, ArtMethod* m) {
   // The upcall can be null and in that case we don't need to do anything.
   if (m == nullptr) {
     return false;
@@ -3519,7 +3512,7 @@
   return instrumentation->IsDeoptimized(m);
 }
 
-bool Dbg::IsForcedInterpreterNeededForUpcallImpl(Thread* thread, mirror::ArtMethod* m) {
+bool Dbg::IsForcedInterpreterNeededForUpcallImpl(Thread* thread, ArtMethod* m) {
   // The upcall can be null and in that case we don't need to do anything.
   if (m == nullptr) {
     return false;
@@ -3623,7 +3616,7 @@
     // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
     // annotalysis.
     bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
-      mirror::ArtMethod* m = GetMethod();
+      ArtMethod* m = GetMethod();
       if (!m->IsRuntimeMethod()) {
         ++stack_depth;
         if (method == nullptr) {
@@ -3639,7 +3632,7 @@
     }
 
     int stack_depth;
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     int32_t line_number;
   };
 
@@ -3701,7 +3694,7 @@
     return JDWP::ERR_OUT_OF_MEMORY;
   }
 
-  mirror::ArtMethod* m = single_step_control->GetMethod();
+  ArtMethod* m = single_step_control->GetMethod();
   const int32_t line_number = visitor.line_number;
   // Note: if the thread is not running Java code (pure native thread), there is no "current"
   // method on the stack (and no line number either).
@@ -3838,7 +3831,7 @@
       return error;
     }
 
-    mirror::ArtMethod* m = FromMethodId(method_id);
+    ArtMethod* m = FromMethodId(method_id);
     if (m->IsStatic() != (receiver == nullptr)) {
       return JDWP::ERR_INVALID_METHODID;
     }
@@ -3860,8 +3853,7 @@
     }
 
     {
-      StackHandleScope<3> hs(soa.Self());
-      HandleWrapper<mirror::ArtMethod> h_m(hs.NewHandleWrapper(&m));
+      StackHandleScope<2> hs(soa.Self());
       HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&receiver));
       HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&c));
       const DexFile::TypeList* types = m->GetParameterTypeList();
@@ -3873,7 +3865,7 @@
         if (shorty[i + 1] == 'L') {
           // Did we really get an argument of an appropriate reference type?
           mirror::Class* parameter_type =
-              h_m->GetClassFromTypeIndex(types->GetTypeItem(i).type_idx_, true);
+              m->GetClassFromTypeIndex(types->GetTypeItem(i).type_idx_, true);
           mirror::Object* argument = gRegistry->Get<mirror::Object*>(arg_values[i], &error);
           if (error != JDWP::ERR_NONE) {
             return JDWP::ERR_INVALID_OBJECT;
@@ -3976,32 +3968,34 @@
 
   // We can be called while an exception is pending. We need
   // to preserve that across the method invocation.
-  StackHandleScope<4> hs(soa.Self());
+  StackHandleScope<3> hs(soa.Self());
   auto old_exception = hs.NewHandle<mirror::Throwable>(soa.Self()->GetException());
   soa.Self()->ClearException();
 
   // Translate the method through the vtable, unless the debugger wants to suppress it.
-  MutableHandle<mirror::ArtMethod> m(hs.NewHandle(pReq->method.Read()));
+  auto* m = pReq->method;
+  auto image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
   if ((pReq->options & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver.Read() != nullptr) {
-    mirror::ArtMethod* actual_method = pReq->klass.Read()->FindVirtualMethodForVirtualOrInterface(m.Get());
-    if (actual_method != m.Get()) {
-      VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m.Get())
+    ArtMethod* actual_method =
+        pReq->klass.Read()->FindVirtualMethodForVirtualOrInterface(m, image_pointer_size);
+    if (actual_method != m) {
+      VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m)
                  << " to " << PrettyMethod(actual_method);
-      m.Assign(actual_method);
+      m = actual_method;
     }
   }
-  VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m.Get())
+  VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m)
              << " receiver=" << pReq->receiver.Read()
              << " arg_count=" << pReq->arg_count;
-  CHECK(m.Get() != nullptr);
+  CHECK(m != nullptr);
 
   CHECK_EQ(sizeof(jvalue), sizeof(uint64_t));
 
   ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(pReq->receiver.Read()));
-  JValue result = InvokeWithJValues(soa, ref.get(), soa.EncodeMethod(m.Get()),
+  JValue result = InvokeWithJValues(soa, ref.get(), soa.EncodeMethod(m),
                                     reinterpret_cast<jvalue*>(pReq->arg_values));
 
-  pReq->result_tag = BasicTagFromDescriptor(m.Get()->GetShorty());
+  pReq->result_tag = BasicTagFromDescriptor(m->GetShorty());
   const bool is_object_result = (pReq->result_tag == JDWP::JT_OBJECT);
   Handle<mirror::Object> object_result = hs.NewHandle(is_object_result ? result.GetL() : nullptr);
   Handle<mirror::Throwable> exception = hs.NewHandle(soa.Self()->GetException());
@@ -4744,7 +4738,7 @@
     if (depth >= kMaxAllocRecordStackDepth) {
       return false;
     }
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     if (!m->IsRuntimeMethod()) {
       record->StackElement(depth)->SetMethod(m);
       record->StackElement(depth)->SetDexPc(GetDexPc());
@@ -4828,7 +4822,7 @@
 
     for (size_t stack_frame = 0; stack_frame < kMaxAllocRecordStackDepth; ++stack_frame) {
       AllocRecordStackTraceElement* stack_element = record->StackElement(stack_frame);
-      mirror::ArtMethod* m = stack_element->Method();
+      ArtMethod* m = stack_element->Method();
       if (m == nullptr) {
         break;
       }
@@ -4884,7 +4878,7 @@
   DISALLOW_COPY_AND_ASSIGN(StringTable);
 };
 
-static const char* GetMethodSourceFile(mirror::ArtMethod* method)
+static const char* GetMethodSourceFile(ArtMethod* method)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(method != nullptr);
   const char* source_file = method->GetDeclaringClassSourceFile();
@@ -4957,7 +4951,7 @@
       std::string temp;
       class_names.Add(record->Type()->GetDescriptor(&temp));
       for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) {
-        mirror::ArtMethod* m = record->StackElement(i)->Method();
+        ArtMethod* m = record->StackElement(i)->Method();
         if (m != nullptr) {
           class_names.Add(m->GetDeclaringClassDescriptor());
           method_names.Add(m->GetName());
@@ -5019,7 +5013,7 @@
         // (2b) method name
         // (2b) method source file
         // (2b) line number, clipped to 32767; -2 if native; -1 if no source
-        mirror::ArtMethod* m = record->StackElement(stack_frame)->Method();
+        ArtMethod* m = record->StackElement(stack_frame)->Method();
         size_t class_name_index = class_names.IndexOf(m->GetDeclaringClassDescriptor());
         size_t method_name_index = method_names.IndexOf(m->GetName());
         size_t file_name_index = filenames.IndexOf(GetMethodSourceFile(m));
@@ -5047,12 +5041,12 @@
   return result;
 }
 
-mirror::ArtMethod* DeoptimizationRequest::Method() const {
+ArtMethod* DeoptimizationRequest::Method() const {
   ScopedObjectAccessUnchecked soa(Thread::Current());
   return soa.DecodeMethod(method_);
 }
 
-void DeoptimizationRequest::SetMethod(mirror::ArtMethod* m) {
+void DeoptimizationRequest::SetMethod(ArtMethod* m) {
   ScopedObjectAccessUnchecked soa(Thread::Current());
   method_ = soa.EncodeMethod(m);
 }
diff --git a/runtime/debugger.h b/runtime/debugger.h
index 811d345..7c586a4 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -37,13 +37,13 @@
 
 namespace art {
 namespace mirror {
-class ArtMethod;
 class Class;
 class Object;
 class Throwable;
 }  // namespace mirror
 class AllocRecord;
 class ArtField;
+class ArtMethod;
 class ObjectRegistry;
 class ScopedObjectAccessUnchecked;
 class StackVisitor;
@@ -54,7 +54,7 @@
  */
 struct DebugInvokeReq {
   DebugInvokeReq(mirror::Object* invoke_receiver, mirror::Class* invoke_class,
-                 mirror::ArtMethod* invoke_method, uint32_t invoke_options,
+                 ArtMethod* invoke_method, uint32_t invoke_options,
                  uint64_t* args, uint32_t args_count)
       : receiver(invoke_receiver), klass(invoke_class), method(invoke_method),
         arg_count(args_count), arg_values(args), options(invoke_options),
@@ -66,7 +66,7 @@
   /* request */
   GcRoot<mirror::Object> receiver;      // not used for ClassType.InvokeMethod
   GcRoot<mirror::Class> klass;
-  GcRoot<mirror::ArtMethod> method;
+  ArtMethod* method;
   const uint32_t arg_count;
   uint64_t* const arg_values;   // will be null if arg_count_ == 0
   const uint32_t options;
@@ -92,7 +92,7 @@
 class SingleStepControl {
  public:
   SingleStepControl(JDWP::JdwpStepSize step_size, JDWP::JdwpStepDepth step_depth,
-                    int stack_depth, mirror::ArtMethod* method)
+                    int stack_depth, ArtMethod* method)
       : step_size_(step_size), step_depth_(step_depth),
         stack_depth_(stack_depth), method_(method) {
   }
@@ -109,17 +109,14 @@
     return stack_depth_;
   }
 
-  mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return method_.Read();
+  ArtMethod* GetMethod() const {
+    return method_;
   }
 
   const std::set<uint32_t>& GetDexPcs() const {
     return dex_pcs_;
   }
 
-  void VisitRoots(RootVisitor* visitor, const RootInfo& root_info)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   void AddDexPc(uint32_t dex_pc);
 
   bool ContainsDexPc(uint32_t dex_pc) const;
@@ -138,7 +135,8 @@
   // set of DEX pcs associated to the source line number where the suspension occurred.
   // This is used to support SD_INTO and SD_OVER single-step depths so we detect when a single-step
   // causes the execution of an instruction in a different method or at a different line number.
-  GcRoot<mirror::ArtMethod> method_;
+  ArtMethod* method_;
+
   std::set<uint32_t> dex_pcs_;
 
   DISALLOW_COPY_AND_ASSIGN(SingleStepControl);
@@ -166,9 +164,9 @@
     SetMethod(other.Method());
   }
 
-  mirror::ArtMethod* Method() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* Method() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetMethod(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetMethod(ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Name 'Kind()' would collide with the above enum name.
   Kind GetKind() const {
@@ -256,7 +254,7 @@
   static bool IsJdwpConfigured();
 
   // Returns true if a method has any breakpoints.
-  static bool MethodHasAnyBreakpoints(mirror::ArtMethod* method)
+  static bool MethodHasAnyBreakpoints(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       LOCKS_EXCLUDED(Locks::breakpoint_lock_);
 
@@ -524,10 +522,10 @@
     kMethodEntry    = 0x04,
     kMethodExit     = 0x08,
   };
-  static void PostFieldAccessEvent(mirror::ArtMethod* m, int dex_pc, mirror::Object* this_object,
+  static void PostFieldAccessEvent(ArtMethod* m, int dex_pc, mirror::Object* this_object,
                                    ArtField* f)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  static void PostFieldModificationEvent(mirror::ArtMethod* m, int dex_pc,
+  static void PostFieldModificationEvent(ArtMethod* m, int dex_pc,
                                          mirror::Object* this_object, ArtField* f,
                                          const JValue* field_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -541,7 +539,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void UpdateDebugger(Thread* thread, mirror::Object* this_object,
-                             mirror::ArtMethod* method, uint32_t new_dex_pc,
+                             ArtMethod* method, uint32_t new_dex_pc,
                              int event_flags, const JValue* return_value)
       LOCKS_EXCLUDED(Locks::breakpoint_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -574,7 +572,7 @@
 
   // Indicates whether we need to force the use of interpreter to invoke a method.
   // This allows to single-step or continue into the called method.
-  static bool IsForcedInterpreterNeededForCalling(Thread* thread, mirror::ArtMethod* m)
+  static bool IsForcedInterpreterNeededForCalling(Thread* thread, ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (!IsDebuggerActive()) {
       return false;
@@ -585,7 +583,7 @@
   // Indicates whether we need to force the use of interpreter entrypoint when calling a
   // method through the resolution trampoline. This allows to single-step or continue into
   // the called method.
-  static bool IsForcedInterpreterNeededForResolution(Thread* thread, mirror::ArtMethod* m)
+  static bool IsForcedInterpreterNeededForResolution(Thread* thread, ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (!IsDebuggerActive()) {
       return false;
@@ -596,7 +594,7 @@
   // Indicates whether we need to force the use of instrumentation entrypoint when calling
   // a method through the resolution trampoline. This allows to deoptimize the stack for
   // debugging when we returned from the called method.
-  static bool IsForcedInstrumentationNeededForResolution(Thread* thread, mirror::ArtMethod* m)
+  static bool IsForcedInstrumentationNeededForResolution(Thread* thread, ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (!IsDebuggerActive()) {
       return false;
@@ -607,7 +605,7 @@
   // Indicates whether we need to force the use of interpreter when returning from the
   // interpreter into the runtime. This allows to deoptimize the stack and continue
   // execution with interpreter for debugging.
-  static bool IsForcedInterpreterNeededForUpcall(Thread* thread, mirror::ArtMethod* m)
+  static bool IsForcedInterpreterNeededForUpcall(Thread* thread, ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (!IsDebuggerActive()) {
       return false;
@@ -709,7 +707,7 @@
   static JDWP::FieldId ToFieldId(const ArtField* f)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static void SetJdwpLocation(JDWP::JdwpLocation* location, mirror::ArtMethod* m, uint32_t dex_pc)
+  static void SetJdwpLocation(JDWP::JdwpLocation* location, ArtMethod* m, uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static JDWP::JdwpState* GetJdwpState();
@@ -733,7 +731,7 @@
   static void PostThreadStartOrStop(Thread*, uint32_t)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static void PostLocationEvent(mirror::ArtMethod* method, int pcOffset,
+  static void PostLocationEvent(ArtMethod* method, int pcOffset,
                                 mirror::Object* thisPtr, int eventFlags,
                                 const JValue* return_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -745,16 +743,16 @@
       EXCLUSIVE_LOCKS_REQUIRED(Locks::deoptimization_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static bool IsForcedInterpreterNeededForCallingImpl(Thread* thread, mirror::ArtMethod* m)
+  static bool IsForcedInterpreterNeededForCallingImpl(Thread* thread, ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static bool IsForcedInterpreterNeededForResolutionImpl(Thread* thread, mirror::ArtMethod* m)
+  static bool IsForcedInterpreterNeededForResolutionImpl(Thread* thread, ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static bool IsForcedInstrumentationNeededForResolutionImpl(Thread* thread, mirror::ArtMethod* m)
+  static bool IsForcedInstrumentationNeededForResolutionImpl(Thread* thread, ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static bool IsForcedInterpreterNeededForUpcallImpl(Thread* thread, mirror::ArtMethod* m)
+  static bool IsForcedInterpreterNeededForUpcallImpl(Thread* thread, ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static AllocRecord* recent_allocation_records_ PT_GUARDED_BY(Locks::alloc_tracker_lock_);
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index dfe5a04..25d5ef4 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -28,6 +28,7 @@
 #include <sstream>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/stringprintf.h"
 #include "class_linker.h"
@@ -35,7 +36,6 @@
 #include "dex_file_verifier.h"
 #include "globals.h"
 #include "leb128.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/string.h"
 #include "os.h"
 #include "safe_map.h"
@@ -760,7 +760,7 @@
   return Signature(this, *proto_id);
 }
 
-int32_t DexFile::GetLineNumFromPC(mirror::ArtMethod* method, uint32_t rel_pc) const {
+int32_t DexFile::GetLineNumFromPC(ArtMethod* method, uint32_t rel_pc) const {
   // For native method, lineno should be -2 to indicate it is native. Note that
   // "line number == -2" is how libcore tells from StackTraceElement.
   if (method->GetCodeItemOffset() == 0) {
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 84eaa4a..d017601 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -37,11 +37,11 @@
 // TODO: remove dependencies on mirror classes, primarily by moving
 // EncodedStaticFieldValueIterator to its own file.
 namespace mirror {
-  class ArtMethod;
   class ClassLoader;
   class DexCache;
 }  // namespace mirror
 class ArtField;
+class ArtMethod;
 class ClassLinker;
 class MemMap;
 class OatDexFile;
@@ -861,7 +861,7 @@
   // Returns -2 for native methods (as expected in exception traces).
   //
   // This is used by runtime; therefore use art::Method not art::DexFile::Method.
-  int32_t GetLineNumFromPC(mirror::ArtMethod* method, uint32_t rel_pc) const
+  int32_t GetLineNumFromPC(ArtMethod* method, uint32_t rel_pc) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void DecodeDebugInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx,
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 526fb8d..dbd24a2 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -19,6 +19,7 @@
 
 #include "entrypoint_utils.h"
 
+#include "art_method.h"
 #include "class_linker-inl.h"
 #include "common_throws.h"
 #include "dex_file.h"
@@ -27,7 +28,6 @@
 #include "indirect_reference_table.h"
 #include "invoke_type.h"
 #include "jni_internal.h"
-#include "mirror/art_method.h"
 #include "mirror/array.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
@@ -38,11 +38,11 @@
 
 namespace art {
 
-inline mirror::ArtMethod* GetResolvedMethod(mirror::ArtMethod* outer_method,
-                                            uint32_t method_index,
-                                            InvokeType invoke_type)
+inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
+                                    uint32_t method_index,
+                                    InvokeType invoke_type)
   SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ArtMethod* caller = outer_method->GetDexCacheResolvedMethod(method_index);
+  ArtMethod* caller = outer_method->GetDexCacheResolvedMethod(method_index, sizeof(void*));
   if (!caller->IsRuntimeMethod()) {
     return caller;
   }
@@ -51,27 +51,25 @@
   // the stub that will then update the dex cache. Therefore, we need to do the
   // resolution ourselves.
 
-  StackHandleScope<3> hs(Thread::Current());
+  StackHandleScope<2> hs(Thread::Current());
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Handle<mirror::ArtMethod> outer(hs.NewHandle(outer_method));
-  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(outer->GetClassLoader()));
-  Handle<mirror::DexCache> dex_cache(hs.NewHandle(outer->GetDexCache()));
-  Handle<mirror::ArtMethod> referrer;
+  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(outer_method->GetClassLoader()));
+  Handle<mirror::DexCache> dex_cache(hs.NewHandle(outer_method->GetDexCache()));
   return class_linker->ResolveMethod(
-      *outer->GetDexFile(), method_index, dex_cache, class_loader, referrer, invoke_type);
+      *outer_method->GetDexFile(), method_index, dex_cache, class_loader, nullptr, invoke_type);
 }
 
-inline mirror::ArtMethod* GetCalleeSaveMethodCaller(StackReference<mirror::ArtMethod>* sp,
-                                                    Runtime::CalleeSaveType type,
-                                                    bool do_caller_check = false)
+inline ArtMethod* GetCalleeSaveMethodCaller(ArtMethod** sp,
+                                            Runtime::CalleeSaveType type,
+                                            bool do_caller_check = false)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  DCHECK_EQ(sp->AsMirrorPtr(), Runtime::Current()->GetCalleeSaveMethod(type));
+  DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(type));
 
   const size_t callee_frame_size = GetCalleeSaveFrameSize(kRuntimeISA, type);
-  auto* caller_sp = reinterpret_cast<StackReference<mirror::ArtMethod>*>(
-          reinterpret_cast<uintptr_t>(sp) + callee_frame_size);
-  mirror::ArtMethod* outer_method = caller_sp->AsMirrorPtr();
-  mirror::ArtMethod* caller = outer_method;
+  auto** caller_sp = reinterpret_cast<ArtMethod**>(
+      reinterpret_cast<uintptr_t>(sp) + callee_frame_size);
+  ArtMethod* outer_method = *caller_sp;
+  ArtMethod* caller = outer_method;
 
   if ((outer_method != nullptr) && outer_method->IsOptimized(sizeof(void*))) {
     const size_t callee_return_pc_offset = GetCalleeSaveReturnPcOffset(kRuntimeISA, type);
@@ -101,7 +99,7 @@
   return caller;
 }
 
-inline mirror::ArtMethod* GetCalleeSaveMethodCaller(Thread* self, Runtime::CalleeSaveType type)
+inline ArtMethod* GetCalleeSaveMethodCaller(Thread* self, Runtime::CalleeSaveType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return GetCalleeSaveMethodCaller(
       self->GetManagedStack()->GetTopQuickFrame(), type, true /* do_caller_check */);
@@ -110,7 +108,7 @@
 template <const bool kAccessCheck>
 ALWAYS_INLINE
 inline mirror::Class* CheckObjectAlloc(uint32_t type_idx,
-                                       mirror::ArtMethod* method,
+                                       ArtMethod* method,
                                        Thread* self, bool* slow_path) {
   mirror::Class* klass = method->GetDexCacheResolvedType<false>(type_idx);
   if (UNLIKELY(klass == nullptr)) {
@@ -191,7 +189,7 @@
 template <bool kAccessCheck, bool kInstrumented>
 ALWAYS_INLINE
 inline mirror::Object* AllocObjectFromCode(uint32_t type_idx,
-                                           mirror::ArtMethod* method,
+                                           ArtMethod* method,
                                            Thread* self,
                                            gc::AllocatorType allocator_type) {
   bool slow_path = false;
@@ -243,7 +241,7 @@
 ALWAYS_INLINE
 inline mirror::Class* CheckArrayAlloc(uint32_t type_idx,
                                       int32_t component_count,
-                                      mirror::ArtMethod* method,
+                                      ArtMethod* method,
                                       bool* slow_path) {
   if (UNLIKELY(component_count < 0)) {
     ThrowNegativeArraySizeException(component_count);
@@ -279,7 +277,7 @@
 ALWAYS_INLINE
 inline mirror::Array* AllocArrayFromCode(uint32_t type_idx,
                                          int32_t component_count,
-                                         mirror::ArtMethod* method,
+                                         ArtMethod* method,
                                          Thread* self,
                                          gc::AllocatorType allocator_type) {
   bool slow_path = false;
@@ -302,7 +300,7 @@
 ALWAYS_INLINE
 inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass,
                                                  int32_t component_count,
-                                                 mirror::ArtMethod* method,
+                                                 ArtMethod* method,
                                                  Thread* self,
                                                  gc::AllocatorType allocator_type) {
   DCHECK(klass != nullptr);
@@ -324,7 +322,7 @@
 }
 
 template<FindFieldType type, bool access_check>
-inline ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
+inline ArtField* FindFieldFromCode(uint32_t field_idx, ArtMethod* referrer,
                                            Thread* self, size_t expected_size) {
   bool is_primitive;
   bool is_set;
@@ -397,8 +395,8 @@
 #define EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, _access_check) \
 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE \
 ArtField* FindFieldFromCode<_type, _access_check>(uint32_t field_idx, \
-                                                          mirror::ArtMethod* referrer, \
-                                                          Thread* self, size_t expected_size) \
+                                                  ArtMethod* referrer, \
+                                                  Thread* self, size_t expected_size) \
 
 #define EXPLICIT_FIND_FIELD_FROM_CODE_TYPED_TEMPLATE_DECL(_type) \
     EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL(_type, false); \
@@ -417,17 +415,16 @@
 #undef EXPLICIT_FIND_FIELD_FROM_CODE_TEMPLATE_DECL
 
 template<InvokeType type, bool access_check>
-inline mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx,
-                                             mirror::Object** this_object,
-                                             mirror::ArtMethod** referrer, Thread* self) {
+inline ArtMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object** this_object,
+                                     ArtMethod** referrer, Thread* self) {
   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
-  mirror::ArtMethod* resolved_method = class_linker->GetResolvedMethod(method_idx, *referrer);
+  ArtMethod* resolved_method = class_linker->GetResolvedMethod(method_idx, *referrer);
   if (resolved_method == nullptr) {
     StackHandleScope<1> hs(self);
     mirror::Object* null_this = nullptr;
     HandleWrapper<mirror::Object> h_this(
         hs.NewHandleWrapper(type == kStatic ? &null_this : this_object));
-    resolved_method = class_linker->ResolveMethod(self, method_idx, referrer, type);
+    resolved_method = class_linker->ResolveMethod(self, method_idx, *referrer, type);
   }
   if (UNLIKELY(resolved_method == nullptr)) {
     DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
@@ -470,7 +467,7 @@
         return nullptr;  // Failure.
       }
       DCHECK(klass->HasVTable()) << PrettyClass(klass);
-      return klass->GetVTableEntry(vtable_index);
+      return klass->GetVTableEntry(vtable_index, class_linker->GetImagePointerSize());
     }
     case kSuper: {
       mirror::Class* super_class = (*referrer)->GetDeclaringClass()->GetSuperClass();
@@ -489,23 +486,25 @@
         DCHECK(super_class != nullptr);
       }
       DCHECK(super_class->HasVTable());
-      return super_class->GetVTableEntry(vtable_index);
+      return super_class->GetVTableEntry(vtable_index, class_linker->GetImagePointerSize());
     }
     case kInterface: {
       uint32_t imt_index = resolved_method->GetDexMethodIndex() % mirror::Class::kImtSize;
-      mirror::ArtMethod* imt_method = (*this_object)->GetClass()->GetEmbeddedImTableEntry(imt_index);
+      ArtMethod* imt_method = (*this_object)->GetClass()->GetEmbeddedImTableEntry(
+          imt_index, class_linker->GetImagePointerSize());
       if (!imt_method->IsImtConflictMethod() && !imt_method->IsImtUnimplementedMethod()) {
         if (kIsDebugBuild) {
           mirror::Class* klass = (*this_object)->GetClass();
-          mirror::ArtMethod* method = klass->FindVirtualMethodForInterface(resolved_method);
+          ArtMethod* method = klass->FindVirtualMethodForInterface(
+              resolved_method, class_linker->GetImagePointerSize());
           CHECK_EQ(imt_method, method) << PrettyMethod(resolved_method) << " / " <<
               PrettyMethod(imt_method) << " / " << PrettyMethod(method) << " / " <<
               PrettyClass(klass);
         }
         return imt_method;
       } else {
-        mirror::ArtMethod* interface_method =
-            (*this_object)->GetClass()->FindVirtualMethodForInterface(resolved_method);
+        ArtMethod* interface_method = (*this_object)->GetClass()->FindVirtualMethodForInterface(
+            resolved_method, class_linker->GetImagePointerSize());
         if (UNLIKELY(interface_method == nullptr)) {
           ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method,
                                                                      *this_object, *referrer);
@@ -523,10 +522,10 @@
 // Explicit template declarations of FindMethodFromCode for all invoke types.
 #define EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, _access_check)                 \
   template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE                       \
-  mirror::ArtMethod* FindMethodFromCode<_type, _access_check>(uint32_t method_idx,         \
-                                                              mirror::Object** this_object, \
-                                                              mirror::ArtMethod** referrer, \
-                                                              Thread* self)
+  ArtMethod* FindMethodFromCode<_type, _access_check>(uint32_t method_idx,         \
+                                                      mirror::Object** this_object, \
+                                                      ArtMethod** referrer, \
+                                                      Thread* self)
 #define EXPLICIT_FIND_METHOD_FROM_CODE_TYPED_TEMPLATE_DECL(_type) \
     EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, false);   \
     EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL(_type, true)
@@ -541,9 +540,8 @@
 #undef EXPLICIT_FIND_METHOD_FROM_CODE_TEMPLATE_DECL
 
 // Fast path field resolution that can't initialize classes or throw exceptions.
-inline ArtField* FindFieldFast(uint32_t field_idx,
-                                       mirror::ArtMethod* referrer,
-                                       FindFieldType type, size_t expected_size) {
+inline ArtField* FindFieldFast(uint32_t field_idx, ArtMethod* referrer, FindFieldType type,
+                               size_t expected_size) {
   ArtField* resolved_field =
       referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx, sizeof(void*));
   if (UNLIKELY(resolved_field == nullptr)) {
@@ -580,8 +578,7 @@
   }
   mirror::Class* referring_class = referrer->GetDeclaringClass();
   if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
-               !referring_class->CanAccessMember(fields_class,
-                                                 resolved_field->GetAccessFlags()) ||
+               !referring_class->CanAccessMember(fields_class, resolved_field->GetAccessFlags()) ||
                (is_set && resolved_field->IsFinal() && (fields_class != referring_class)))) {
     // Illegal access.
     return nullptr;
@@ -594,15 +591,13 @@
 }
 
 // Fast path method resolution that can't throw exceptions.
-inline mirror::ArtMethod* FindMethodFast(uint32_t method_idx,
-                                         mirror::Object* this_object,
-                                         mirror::ArtMethod* referrer,
-                                         bool access_check, InvokeType type) {
+inline ArtMethod* FindMethodFast(uint32_t method_idx, mirror::Object* this_object,
+                                 ArtMethod* referrer, bool access_check, InvokeType type) {
   if (UNLIKELY(this_object == nullptr && type != kStatic)) {
     return nullptr;
   }
-  mirror::ArtMethod* resolved_method =
-      referrer->GetDeclaringClass()->GetDexCache()->GetResolvedMethod(method_idx);
+  ArtMethod* resolved_method =
+      referrer->GetDeclaringClass()->GetDexCache()->GetResolvedMethod(method_idx, sizeof(void*));
   if (UNLIKELY(resolved_method == nullptr)) {
     return nullptr;
   }
@@ -622,22 +617,21 @@
     }
   }
   if (type == kInterface) {  // Most common form of slow path dispatch.
-    return this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
+    return this_object->GetClass()->FindVirtualMethodForInterface(resolved_method, sizeof(void*));
   } else if (type == kStatic || type == kDirect) {
     return resolved_method;
   } else if (type == kSuper) {
-    return referrer->GetDeclaringClass()->GetSuperClass()
-                   ->GetVTableEntry(resolved_method->GetMethodIndex());
+    return referrer->GetDeclaringClass()->GetSuperClass()->GetVTableEntry(
+        resolved_method->GetMethodIndex(), sizeof(void*));
   } else {
     DCHECK(type == kVirtual);
-    return this_object->GetClass()->GetVTableEntry(resolved_method->GetMethodIndex());
+    return this_object->GetClass()->GetVTableEntry(
+        resolved_method->GetMethodIndex(), sizeof(void*));
   }
 }
 
-inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx,
-                                                    mirror::ArtMethod* referrer,
-                                                    Thread* self, bool can_run_clinit,
-                                                    bool verify_access) {
+inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx, ArtMethod* referrer, Thread* self,
+                                             bool can_run_clinit, bool verify_access) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   mirror::Class* klass = class_linker->ResolveType(type_idx, referrer);
   if (UNLIKELY(klass == nullptr)) {
@@ -670,8 +664,7 @@
   return h_class.Get();
 }
 
-inline mirror::String* ResolveStringFromCode(mirror::ArtMethod* referrer,
-                                             uint32_t string_idx) {
+inline mirror::String* ResolveStringFromCode(ArtMethod* referrer, uint32_t string_idx) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   return class_linker->ResolveString(string_idx, referrer);
 }
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index ce56739..fc7f8b7 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -17,11 +17,11 @@
 #include "entrypoints/entrypoint_utils.h"
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/mutex.h"
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/method.h"
 #include "mirror/object-inl.h"
@@ -35,7 +35,7 @@
 
 static inline mirror::Class* CheckFilledNewArrayAlloc(uint32_t type_idx,
                                                       int32_t component_count,
-                                                      mirror::ArtMethod* referrer,
+                                                      ArtMethod* referrer,
                                                       Thread* self,
                                                       bool access_check)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -76,7 +76,7 @@
 
 // Helper function to allocate array for FILLED_NEW_ARRAY.
 mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, int32_t component_count,
-                                          mirror::ArtMethod* referrer, Thread* self,
+                                          ArtMethod* referrer, Thread* self,
                                           bool access_check,
                                           gc::AllocatorType /* allocator_type */) {
   mirror::Class* klass = CheckFilledNewArrayAlloc(type_idx, component_count, referrer, self,
@@ -96,7 +96,7 @@
 // Helper function to allocate array for FILLED_NEW_ARRAY.
 mirror::Array* CheckAndAllocArrayFromCodeInstrumented(uint32_t type_idx,
                                                       int32_t component_count,
-                                                      mirror::ArtMethod* referrer,
+                                                      ArtMethod* referrer,
                                                       Thread* self,
                                                       bool access_check,
                                                       gc::AllocatorType /* allocator_type */) {
@@ -294,22 +294,19 @@
       mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
       mirror::Class* proxy_class = rcvr->GetClass();
       mirror::Method* interface_method = soa.Decode<mirror::Method*>(interface_method_jobj);
-      mirror::ArtMethod* proxy_method =
-          rcvr->GetClass()->FindVirtualMethodForInterface(interface_method->GetArtMethod());
-      int throws_index = -1;
-      size_t num_virt_methods = proxy_class->NumVirtualMethods();
-      for (size_t i = 0; i < num_virt_methods; i++) {
-        if (proxy_class->GetVirtualMethod(i) == proxy_method) {
-          throws_index = i;
-          break;
-        }
-      }
-      CHECK_NE(throws_index, -1);
+      ArtMethod* proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(
+          interface_method->GetArtMethod(), sizeof(void*));
+      auto* virtual_methods = proxy_class->GetVirtualMethodsPtr();
+      size_t num_virtuals = proxy_class->NumVirtualMethods();
+      size_t method_size = ArtMethod::ObjectSize(sizeof(void*));
+      int throws_index = (reinterpret_cast<uintptr_t>(proxy_method) -
+          reinterpret_cast<uintptr_t>(virtual_methods)) / method_size;
+      CHECK_LT(throws_index, static_cast<int>(num_virtuals));
       mirror::ObjectArray<mirror::Class>* declared_exceptions =
           proxy_class->GetThrows()->Get(throws_index);
       mirror::Class* exception_class = exception->GetClass();
       bool declares_exception = false;
-      for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
+      for (int32_t i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
         mirror::Class* declared_exception = declared_exceptions->Get(i);
         declares_exception = declared_exception->IsAssignableFrom(exception_class);
       }
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 8d419f8..47865a2 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -31,19 +31,19 @@
 
 namespace mirror {
   class Array;
-  class ArtMethod;
   class Class;
   class Object;
   class String;
 }  // namespace mirror
 
 class ArtField;
+class ArtMethod;
 class ScopedObjectAccessAlreadyRunnable;
 class Thread;
 
 template <const bool kAccessCheck>
 ALWAYS_INLINE inline mirror::Class* CheckObjectAlloc(uint32_t type_idx,
-                                                     mirror::ArtMethod* method,
+                                                     ArtMethod* method,
                                                      Thread* self, bool* slow_path)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -58,7 +58,7 @@
 // check.
 template <bool kAccessCheck, bool kInstrumented>
 ALWAYS_INLINE inline mirror::Object* AllocObjectFromCode(uint32_t type_idx,
-                                                         mirror::ArtMethod* method,
+                                                         ArtMethod* method,
                                                          Thread* self,
                                                          gc::AllocatorType allocator_type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -81,7 +81,7 @@
 template <bool kAccessCheck>
 ALWAYS_INLINE inline mirror::Class* CheckArrayAlloc(uint32_t type_idx,
                                                     int32_t component_count,
-                                                    mirror::ArtMethod* method,
+                                                    ArtMethod* method,
                                                     bool* slow_path)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -92,7 +92,7 @@
 template <bool kAccessCheck, bool kInstrumented>
 ALWAYS_INLINE inline mirror::Array* AllocArrayFromCode(uint32_t type_idx,
                                                        int32_t component_count,
-                                                       mirror::ArtMethod* method,
+                                                       ArtMethod* method,
                                                        Thread* self,
                                                        gc::AllocatorType allocator_type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -100,20 +100,20 @@
 template <bool kAccessCheck, bool kInstrumented>
 ALWAYS_INLINE inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass,
                                                                int32_t component_count,
-                                                               mirror::ArtMethod* method,
+                                                               ArtMethod* method,
                                                                Thread* self,
                                                                gc::AllocatorType allocator_type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 extern mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, int32_t component_count,
-                                                 mirror::ArtMethod* method, Thread* self,
+                                                 ArtMethod* method, Thread* self,
                                                  bool access_check,
                                                  gc::AllocatorType allocator_type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 extern mirror::Array* CheckAndAllocArrayFromCodeInstrumented(uint32_t type_idx,
                                                              int32_t component_count,
-                                                             mirror::ArtMethod* method,
+                                                             ArtMethod* method,
                                                              Thread* self,
                                                              bool access_check,
                                                              gc::AllocatorType allocator_type)
@@ -132,38 +132,33 @@
 };
 
 template<FindFieldType type, bool access_check>
-inline ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
-                                           Thread* self, size_t expected_size)
+inline ArtField* FindFieldFromCode(
+    uint32_t field_idx, ArtMethod* referrer, Thread* self, size_t expected_size)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 template<InvokeType type, bool access_check>
-inline mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx,
-                                             mirror::Object** this_object,
-                                             mirror::ArtMethod** referrer, Thread* self)
+inline ArtMethod* FindMethodFromCode(
+    uint32_t method_idx, mirror::Object** this_object, ArtMethod** referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 // Fast path field resolution that can't initialize classes or throw exceptions.
-inline ArtField* FindFieldFast(uint32_t field_idx,
-                                       mirror::ArtMethod* referrer,
-                                       FindFieldType type, size_t expected_size)
+inline ArtField* FindFieldFast(
+    uint32_t field_idx, ArtMethod* referrer, FindFieldType type, size_t expected_size)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 // Fast path method resolution that can't throw exceptions.
-inline mirror::ArtMethod* FindMethodFast(uint32_t method_idx,
-                                         mirror::Object* this_object,
-                                         mirror::ArtMethod* referrer,
-                                         bool access_check, InvokeType type)
+inline ArtMethod* FindMethodFast(
+    uint32_t method_idx, mirror::Object* this_object, ArtMethod* referrer, bool access_check,
+    InvokeType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx,
-                                             mirror::ArtMethod* referrer,
-                                             Thread* self, bool can_run_clinit,
-                                             bool verify_access)
+inline mirror::Class* ResolveVerifyAndClinit(
+    uint32_t type_idx, ArtMethod* referrer, Thread* self, bool can_run_clinit, bool verify_access)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 extern void ThrowStackOverflowError(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-inline mirror::String* ResolveStringFromCode(mirror::ArtMethod* referrer, uint32_t string_idx)
+inline mirror::String* ResolveStringFromCode(ArtMethod* referrer, uint32_t string_idx)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 // TODO: annotalysis disabled as monitor semantics are maintained in Java code.
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index d4844c2..72c2e0a 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
+#include "art_method-inl.h"
 #include "class_linker.h"
 #include "dex_file-inl.h"
 #include "interpreter/interpreter.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/object-inl.h"
 #include "reflection.h"
 #include "runtime.h"
@@ -27,7 +27,7 @@
 
 extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, const DexFile::CodeItem* code_item,
                                                    ShadowFrame* shadow_frame, JValue* result) {
-  mirror::ArtMethod* method = shadow_frame->GetMethod();
+  ArtMethod* method = shadow_frame->GetMethod();
   // Ensure static methods are initialized.
   if (method->IsStatic()) {
     mirror::Class* declaringClass = method->GetDeclaringClass();
@@ -50,7 +50,7 @@
   uint16_t arg_offset = (code_item == nullptr) ? 0 : code_item->registers_size_ - code_item->ins_size_;
   method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset),
                  (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t),
-                 result, method->GetShorty());
+                 result, method->GetInterfaceMethodIfProxy(sizeof(void*))->GetShorty());
 }
 
 }  // namespace art
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc
index a68eeeb..22226c1 100644
--- a/runtime/entrypoints/jni/jni_entrypoints.cc
+++ b/runtime/entrypoints/jni/jni_entrypoints.cc
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "entrypoints/entrypoint_utils.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/object-inl.h"
 #include "scoped_thread_state_change.h"
 #include "thread.h"
@@ -34,7 +34,7 @@
   Locks::mutator_lock_->AssertNotHeld(self);  // We come here as Native.
   ScopedObjectAccess soa(self);
 
-  mirror::ArtMethod* method = self->GetCurrentMethod(nullptr);
+  ArtMethod* method = self->GetCurrentMethod(nullptr);
   DCHECK(method != nullptr);
 
   // Lookup symbol address for method, on failure we'll return null with an exception set,
diff --git a/runtime/entrypoints/quick/callee_save_frame.h b/runtime/entrypoints/quick/callee_save_frame.h
index 3bcaf93..7a44158 100644
--- a/runtime/entrypoints/quick/callee_save_frame.h
+++ b/runtime/entrypoints/quick/callee_save_frame.h
@@ -32,9 +32,7 @@
 #include "arch/x86_64/quick_method_frame_info_x86_64.h"
 
 namespace art {
-namespace mirror {
 class ArtMethod;
-}  // namespace mirror
 
 class ScopedQuickEntrypointChecks {
  public:
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
index fa129af..f56b5e4 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
@@ -16,9 +16,9 @@
 
 #include "entrypoints/quick/quick_alloc_entrypoints.h"
 
+#include "art_method-inl.h"
 #include "callee_save_frame.h"
 #include "entrypoints/entrypoint_utils-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
@@ -29,7 +29,7 @@
 
 #define GENERATE_ENTRYPOINTS_FOR_ALLOCATOR_INST(suffix, suffix2, instrumented_bool, allocator_type) \
 extern "C" mirror::Object* artAllocObjectFromCode ##suffix##suffix2( \
-    uint32_t type_idx, mirror::ArtMethod* method, Thread* self) \
+    uint32_t type_idx, ArtMethod* method, Thread* self) \
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
   ScopedQuickEntrypointChecks sqec(self); \
   if (kUseTlabFastPath && !instrumented_bool && allocator_type == gc::kAllocatorTypeTLAB) { \
@@ -56,7 +56,7 @@
   return AllocObjectFromCode<false, instrumented_bool>(type_idx, method, self, allocator_type); \
 } \
 extern "C" mirror::Object* artAllocObjectFromCodeResolved##suffix##suffix2( \
-    mirror::Class* klass, mirror::ArtMethod* method, Thread* self) \
+    mirror::Class* klass, ArtMethod* method, Thread* self) \
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
   UNUSED(method); \
   ScopedQuickEntrypointChecks sqec(self); \
@@ -83,7 +83,7 @@
   return AllocObjectFromCodeResolved<instrumented_bool>(klass, self, allocator_type); \
 } \
 extern "C" mirror::Object* artAllocObjectFromCodeInitialized##suffix##suffix2( \
-    mirror::Class* klass, mirror::ArtMethod* method, Thread* self) \
+    mirror::Class* klass, ArtMethod* method, Thread* self) \
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
   UNUSED(method); \
   ScopedQuickEntrypointChecks sqec(self); \
@@ -108,34 +108,34 @@
   return AllocObjectFromCodeInitialized<instrumented_bool>(klass, self, allocator_type); \
 } \
 extern "C" mirror::Object* artAllocObjectFromCodeWithAccessCheck##suffix##suffix2( \
-    uint32_t type_idx, mirror::ArtMethod* method, Thread* self) \
+    uint32_t type_idx, ArtMethod* method, Thread* self) \
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
   ScopedQuickEntrypointChecks sqec(self); \
   return AllocObjectFromCode<true, instrumented_bool>(type_idx, method, self, allocator_type); \
 } \
 extern "C" mirror::Array* artAllocArrayFromCode##suffix##suffix2( \
-    uint32_t type_idx, int32_t component_count, mirror::ArtMethod* method, Thread* self) \
+    uint32_t type_idx, int32_t component_count, ArtMethod* method, Thread* self) \
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
   ScopedQuickEntrypointChecks sqec(self); \
   return AllocArrayFromCode<false, instrumented_bool>(type_idx, component_count, method, self, \
                                                       allocator_type); \
 } \
 extern "C" mirror::Array* artAllocArrayFromCodeResolved##suffix##suffix2( \
-    mirror::Class* klass, int32_t component_count, mirror::ArtMethod* method, Thread* self) \
+    mirror::Class* klass, int32_t component_count, ArtMethod* method, Thread* self) \
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
   ScopedQuickEntrypointChecks sqec(self); \
   return AllocArrayFromCodeResolved<false, instrumented_bool>(klass, component_count, method, self, \
                                                               allocator_type); \
 } \
 extern "C" mirror::Array* artAllocArrayFromCodeWithAccessCheck##suffix##suffix2( \
-    uint32_t type_idx, int32_t component_count, mirror::ArtMethod* method, Thread* self) \
+    uint32_t type_idx, int32_t component_count, ArtMethod* method, Thread* self) \
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
   ScopedQuickEntrypointChecks sqec(self); \
   return AllocArrayFromCode<true, instrumented_bool>(type_idx, component_count, method, self, \
                                                      allocator_type); \
 } \
 extern "C" mirror::Array* artCheckAndAllocArrayFromCode##suffix##suffix2( \
-    uint32_t type_idx, int32_t component_count, mirror::ArtMethod* method, Thread* self) \
+    uint32_t type_idx, int32_t component_count, ArtMethod* method, Thread* self) \
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
   ScopedQuickEntrypointChecks sqec(self); \
   if (!instrumented_bool) { \
@@ -145,7 +145,7 @@
   } \
 } \
 extern "C" mirror::Array* artCheckAndAllocArrayFromCodeWithAccessCheck##suffix##suffix2( \
-    uint32_t type_idx, int32_t component_count, mirror::ArtMethod* method, Thread* self) \
+    uint32_t type_idx, int32_t component_count, ArtMethod* method, Thread* self) \
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \
   ScopedQuickEntrypointChecks sqec(self); \
   if (!instrumented_bool) { \
@@ -193,27 +193,27 @@
 GENERATE_ENTRYPOINTS_FOR_ALLOCATOR(RegionTLAB, gc::kAllocatorTypeRegionTLAB)
 
 #define GENERATE_ENTRYPOINTS(suffix) \
-extern "C" void* art_quick_alloc_array##suffix(uint32_t, int32_t, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_array_resolved##suffix(mirror::Class* klass, int32_t, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_array_with_access_check##suffix(uint32_t, int32_t, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_object##suffix(uint32_t type_idx, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_object_resolved##suffix(mirror::Class* klass, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_object_initialized##suffix(mirror::Class* klass, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_object_with_access_check##suffix(uint32_t type_idx, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_check_and_alloc_array##suffix(uint32_t, int32_t, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_check_and_alloc_array_with_access_check##suffix(uint32_t, int32_t, mirror::ArtMethod* ref); \
+extern "C" void* art_quick_alloc_array##suffix(uint32_t, int32_t, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_array_resolved##suffix(mirror::Class* klass, int32_t, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_array_with_access_check##suffix(uint32_t, int32_t, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_object##suffix(uint32_t type_idx, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_object_resolved##suffix(mirror::Class* klass, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_object_initialized##suffix(mirror::Class* klass, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_object_with_access_check##suffix(uint32_t type_idx, ArtMethod* ref); \
+extern "C" void* art_quick_check_and_alloc_array##suffix(uint32_t, int32_t, ArtMethod* ref); \
+extern "C" void* art_quick_check_and_alloc_array_with_access_check##suffix(uint32_t, int32_t, ArtMethod* ref); \
 extern "C" void* art_quick_alloc_string_from_bytes##suffix(void*, int32_t, int32_t, int32_t); \
 extern "C" void* art_quick_alloc_string_from_chars##suffix(int32_t, int32_t, void*); \
 extern "C" void* art_quick_alloc_string_from_string##suffix(void*); \
-extern "C" void* art_quick_alloc_array##suffix##_instrumented(uint32_t, int32_t, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_array_resolved##suffix##_instrumented(mirror::Class* klass, int32_t, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_array_with_access_check##suffix##_instrumented(uint32_t, int32_t, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_object##suffix##_instrumented(uint32_t type_idx, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_object_resolved##suffix##_instrumented(mirror::Class* klass, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_object_initialized##suffix##_instrumented(mirror::Class* klass, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_alloc_object_with_access_check##suffix##_instrumented(uint32_t type_idx, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_check_and_alloc_array##suffix##_instrumented(uint32_t, int32_t, mirror::ArtMethod* ref); \
-extern "C" void* art_quick_check_and_alloc_array_with_access_check##suffix##_instrumented(uint32_t, int32_t, mirror::ArtMethod* ref); \
+extern "C" void* art_quick_alloc_array##suffix##_instrumented(uint32_t, int32_t, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_array_resolved##suffix##_instrumented(mirror::Class* klass, int32_t, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_array_with_access_check##suffix##_instrumented(uint32_t, int32_t, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_object##suffix##_instrumented(uint32_t type_idx, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_object_resolved##suffix##_instrumented(mirror::Class* klass, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_object_initialized##suffix##_instrumented(mirror::Class* klass, ArtMethod* ref); \
+extern "C" void* art_quick_alloc_object_with_access_check##suffix##_instrumented(uint32_t type_idx, ArtMethod* ref); \
+extern "C" void* art_quick_check_and_alloc_array##suffix##_instrumented(uint32_t, int32_t, ArtMethod* ref); \
+extern "C" void* art_quick_check_and_alloc_array_with_access_check##suffix##_instrumented(uint32_t, int32_t, ArtMethod* ref); \
 extern "C" void* art_quick_alloc_string_from_bytes##suffix##_instrumented(void*, int32_t, int32_t, int32_t); \
 extern "C" void* art_quick_alloc_string_from_chars##suffix##_instrumented(int32_t, int32_t, void*); \
 extern "C" void* art_quick_alloc_string_from_string##suffix##_instrumented(void*); \
diff --git a/runtime/entrypoints/quick/quick_default_externs.h b/runtime/entrypoints/quick/quick_default_externs.h
index 1fd8a949a..c7aaa20 100644
--- a/runtime/entrypoints/quick/quick_default_externs.h
+++ b/runtime/entrypoints/quick/quick_default_externs.h
@@ -22,10 +22,10 @@
 namespace art {
 namespace mirror {
 class Array;
-class ArtMethod;
 class Class;
 class Object;
 }  // namespace mirror
+class ArtMethod;
 }  // namespace art
 
 // These are extern declarations of assembly stubs with common names.
@@ -97,9 +97,9 @@
 extern "C" void* art_quick_memcpy(void*, const void*, size_t);
 
 // Invoke entrypoints.
-extern "C" void art_quick_imt_conflict_trampoline(art::mirror::ArtMethod*);
-extern "C" void art_quick_resolution_trampoline(art::mirror::ArtMethod*);
-extern "C" void art_quick_to_interpreter_bridge(art::mirror::ArtMethod*);
+extern "C" void art_quick_imt_conflict_trampoline(art::ArtMethod*);
+extern "C" void art_quick_resolution_trampoline(art::ArtMethod*);
+extern "C" void art_quick_to_interpreter_bridge(art::ArtMethod*);
 extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
 extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
 extern "C" void art_quick_invoke_static_trampoline_with_access_check(uint32_t, void*);
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 1b1ef66..3d42ea0 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "callee_save_frame.h"
 #include "dex_file-inl.h"
 #include "interpreter/interpreter.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 9148878..3cefc47 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
+#include "art_method-inl.h"
 #include "callee_save_frame.h"
 #include "entrypoints/entrypoint_utils-inl.h"
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
 
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index b72ce34..cef2510 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -29,13 +29,13 @@
 
 namespace mirror {
 class Array;
-class ArtMethod;
 class Class;
 class Object;
 template<class MirrorType>
 class CompressedReference;
 }  // namespace mirror
 
+class ArtMethod;
 class Thread;
 
 // Pointers to functions that are called by quick compiler generated code via thread-local storage.
diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h
index 0aca58f..60bbf4a 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_list.h
+++ b/runtime/entrypoints/quick/quick_entrypoints_list.h
@@ -20,15 +20,15 @@
 // All quick entrypoints. Format is name, return type, argument types.
 
 #define QUICK_ENTRYPOINT_LIST(V) \
-  V(AllocArray, void*, uint32_t, int32_t, mirror::ArtMethod*) \
-  V(AllocArrayResolved, void*, mirror::Class*, int32_t, mirror::ArtMethod*) \
-  V(AllocArrayWithAccessCheck, void*, uint32_t, int32_t, mirror::ArtMethod*) \
-  V(AllocObject, void*, uint32_t, mirror::ArtMethod*) \
-  V(AllocObjectResolved, void*, mirror::Class*, mirror::ArtMethod*) \
-  V(AllocObjectInitialized, void*, mirror::Class*, mirror::ArtMethod*) \
-  V(AllocObjectWithAccessCheck, void*, uint32_t, mirror::ArtMethod*) \
-  V(CheckAndAllocArray, void*, uint32_t, int32_t, mirror::ArtMethod*) \
-  V(CheckAndAllocArrayWithAccessCheck, void*, uint32_t, int32_t, mirror::ArtMethod*) \
+  V(AllocArray, void*, uint32_t, int32_t, ArtMethod*) \
+  V(AllocArrayResolved, void*, mirror::Class*, int32_t, ArtMethod*) \
+  V(AllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*) \
+  V(AllocObject, void*, uint32_t, ArtMethod*) \
+  V(AllocObjectResolved, void*, mirror::Class*, ArtMethod*) \
+  V(AllocObjectInitialized, void*, mirror::Class*, ArtMethod*) \
+  V(AllocObjectWithAccessCheck, void*, uint32_t, ArtMethod*) \
+  V(CheckAndAllocArray, void*, uint32_t, int32_t, ArtMethod*) \
+  V(CheckAndAllocArrayWithAccessCheck, void*, uint32_t, int32_t, ArtMethod*) \
   V(AllocStringFromBytes, void*, void*, int32_t, int32_t, int32_t) \
   V(AllocStringFromChars, void*, int32_t, int32_t, void*) \
   V(AllocStringFromString, void*, void*) \
@@ -77,7 +77,7 @@
   V(JniMethodEndSynchronized, void, uint32_t, jobject, Thread*) \
   V(JniMethodEndWithReference, mirror::Object*, jobject, uint32_t, Thread*) \
   V(JniMethodEndWithReferenceSynchronized, mirror::Object*, jobject, uint32_t, jobject, Thread*) \
-  V(QuickGenericJniTrampoline, void, mirror::ArtMethod*) \
+  V(QuickGenericJniTrampoline, void, ArtMethod*) \
 \
   V(LockObject, void, mirror::Object*) \
   V(UnlockObject, void, mirror::Object*) \
@@ -106,9 +106,9 @@
   V(StringCompareTo, int32_t, void*, void*) \
   V(Memcpy, void*, void*, const void*, size_t) \
 \
-  V(QuickImtConflictTrampoline, void, mirror::ArtMethod*) \
-  V(QuickResolutionTrampoline, void, mirror::ArtMethod*) \
-  V(QuickToInterpreterBridge, void, mirror::ArtMethod*) \
+  V(QuickImtConflictTrampoline, void, ArtMethod*) \
+  V(QuickResolutionTrampoline, void, ArtMethod*) \
+  V(QuickToInterpreterBridge, void, ArtMethod*) \
   V(InvokeDirectTrampolineWithAccessCheck, void, uint32_t, void*) \
   V(InvokeInterfaceTrampolineWithAccessCheck, void, uint32_t, void*) \
   V(InvokeStaticTrampolineWithAccessCheck, void, uint32_t, void*) \
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index b5a7c09..871cf3c 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -15,17 +15,17 @@
  */
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "callee_save_frame.h"
 #include "dex_file-inl.h"
 #include "entrypoints/entrypoint_utils-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 
 #include <stdint.h>
 
 namespace art {
 
-extern "C" int8_t artGetByteStaticFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
+extern "C" int8_t artGetByteStaticFromCode(uint32_t field_idx, ArtMethod* referrer,
                                            Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
@@ -40,7 +40,7 @@
   return 0;  // Will throw exception by checking with Thread::Current.
 }
 
-extern "C" uint8_t artGetBooleanStaticFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
+extern "C" uint8_t artGetBooleanStaticFromCode(uint32_t field_idx, ArtMethod* referrer,
                                                Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
@@ -55,7 +55,7 @@
   return 0;  // Will throw exception by checking with Thread::Current.
 }
 
-extern "C" int16_t artGetShortStaticFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
+extern "C" int16_t artGetShortStaticFromCode(uint32_t field_idx, ArtMethod* referrer,
                                              Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
@@ -71,7 +71,7 @@
 }
 
 extern "C" uint16_t artGetCharStaticFromCode(uint32_t field_idx,
-                                             mirror::ArtMethod* referrer,
+                                             ArtMethod* referrer,
                                              Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
@@ -87,7 +87,7 @@
 }
 
 extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx,
-                                           mirror::ArtMethod* referrer,
+                                           ArtMethod* referrer,
                                            Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
@@ -103,7 +103,7 @@
 }
 
 extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx,
-                                           mirror::ArtMethod* referrer,
+                                           ArtMethod* referrer,
                                            Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
@@ -119,7 +119,7 @@
 }
 
 extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx,
-                                                   mirror::ArtMethod* referrer,
+                                                   ArtMethod* referrer,
                                                    Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
@@ -137,7 +137,7 @@
 }
 
 extern "C" int8_t artGetByteInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
-                                             mirror::ArtMethod* referrer, Thread* self)
+                                             ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t));
@@ -157,7 +157,7 @@
 }
 
 extern "C" uint8_t artGetBooleanInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
-                                                 mirror::ArtMethod* referrer, Thread* self)
+                                                 ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t));
@@ -176,7 +176,7 @@
   return 0;  // Will throw exception by checking with Thread::Current.
 }
 extern "C" int16_t artGetShortInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
-                                               mirror::ArtMethod* referrer, Thread* self)
+                                               ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t));
@@ -196,7 +196,7 @@
 }
 
 extern "C" uint16_t artGetCharInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
-                                               mirror::ArtMethod* referrer, Thread* self)
+                                               ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t));
@@ -216,7 +216,7 @@
 }
 
 extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
-                                             mirror::ArtMethod* referrer, Thread* self)
+                                             ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int32_t));
@@ -236,7 +236,7 @@
 }
 
 extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj,
-                                             mirror::ArtMethod* referrer, Thread* self)
+                                             ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int64_t));
@@ -256,7 +256,7 @@
 }
 
 extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
-                                                     mirror::ArtMethod* referrer,
+                                                     ArtMethod* referrer,
                                                      Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
@@ -278,7 +278,7 @@
 }
 
 extern "C" int artSet8StaticFromCode(uint32_t field_idx, uint32_t new_value,
-                                     mirror::ArtMethod* referrer, Thread* self)
+                                     ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int8_t));
@@ -309,7 +309,7 @@
 }
 
 extern "C" int artSet16StaticFromCode(uint32_t field_idx, uint16_t new_value,
-                                      mirror::ArtMethod* referrer, Thread* self)
+                                      ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int16_t));
@@ -340,7 +340,7 @@
 }
 
 extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
-                                      mirror::ArtMethod* referrer, Thread* self)
+                                      ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int32_t));
@@ -358,7 +358,7 @@
   return -1;  // failure
 }
 
-extern "C" int artSet64StaticFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
+extern "C" int artSet64StaticFromCode(uint32_t field_idx, ArtMethod* referrer,
                                       uint64_t new_value, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
@@ -378,7 +378,7 @@
 }
 
 extern "C" int artSetObjStaticFromCode(uint32_t field_idx, mirror::Object* new_value,
-                                       mirror::ArtMethod* referrer, Thread* self)
+                                       ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
@@ -401,7 +401,7 @@
 }
 
 extern "C" int artSet8InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint8_t new_value,
-                                       mirror::ArtMethod* referrer, Thread* self)
+                                       ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int8_t));
@@ -440,7 +440,7 @@
 }
 
 extern "C" int artSet16InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint16_t new_value,
-                                        mirror::ArtMethod* referrer, Thread* self)
+                                        ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int16_t));
@@ -480,7 +480,7 @@
 }
 
 extern "C" int artSet32InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint32_t new_value,
-                                        mirror::ArtMethod* referrer, Thread* self)
+                                        ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int32_t));
@@ -508,7 +508,7 @@
 }
 
 extern "C" int artSet64InstanceFromCode(uint32_t field_idx, mirror::Object* obj, uint64_t new_value,
-                                        mirror::ArtMethod* referrer, Thread* self)
+                                        ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int64_t));
@@ -533,7 +533,7 @@
 
 extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, mirror::Object* obj,
                                          mirror::Object* new_value,
-                                         mirror::ArtMethod* referrer, Thread* self)
+                                         ArtMethod* referrer, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   ArtField* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
diff --git a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
index e336543..d3991cd 100644
--- a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
+#include "art_method-inl.h"
 #include "callee_save_frame.h"
 #include "mirror/array.h"
-#include "mirror/art_method-inl.h"
 #include "entrypoints/entrypoint_utils.h"
 
 namespace art {
@@ -25,7 +25,7 @@
  * Handle fill array data by copying appropriate part of dex file into array.
  */
 extern "C" int artHandleFillArrayDataFromCode(uint32_t payload_offset, mirror::Array* array,
-                                              mirror::ArtMethod* method, Thread* self)
+                                              ArtMethod* method, Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   const uint16_t* const insns = method->GetCodeItem()->insns_;
diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
index 2bb73ef..2b5c15b 100644
--- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
@@ -14,17 +14,17 @@
  * limitations under the License.
  */
 
+#include "art_method-inl.h"
 #include "callee_save_frame.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
 #include "instrumentation.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/object-inl.h"
 #include "runtime.h"
 #include "thread-inl.h"
 
 namespace art {
 
-extern "C" const void* artInstrumentationMethodEntryFromCode(mirror::ArtMethod* method,
+extern "C" const void* artInstrumentationMethodEntryFromCode(ArtMethod* method,
                                                              mirror::Object* this_object,
                                                              Thread* self,
                                                              uintptr_t lr)
@@ -47,8 +47,7 @@
   return result;
 }
 
-extern "C" TwoWordReturn artInstrumentationMethodExitFromCode(Thread* self,
-                                                              StackReference<mirror::ArtMethod>* sp,
+extern "C" TwoWordReturn artInstrumentationMethodExitFromCode(Thread* self, ArtMethod** sp,
                                                               uint64_t gpr_result,
                                                               uint64_t fpr_result)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index 51817a2..de225ad 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
+#include "art_method-inl.h"
 #include "entrypoints/entrypoint_utils-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/object-inl.h"
 #include "thread-inl.h"
 #include "verify_object-inl.h"
@@ -35,7 +35,7 @@
   DCHECK(env != nullptr);
   uint32_t saved_local_ref_cookie = env->local_ref_cookie;
   env->local_ref_cookie = env->locals.GetSegmentState();
-  mirror::ArtMethod* native_method = self->GetManagedStack()->GetTopQuickFrame()->AsMirrorPtr();
+  ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
   if (!native_method->IsFastNative()) {
     // When not fast JNI we transition out of runnable.
     self->TransitionFromRunnableToSuspended(kNative);
@@ -50,7 +50,7 @@
 
 // TODO: NO_THREAD_SAFETY_ANALYSIS due to different control paths depending on fast JNI.
 static void GoToRunnable(Thread* self) NO_THREAD_SAFETY_ANALYSIS {
-  mirror::ArtMethod* native_method = self->GetManagedStack()->GetTopQuickFrame()->AsMirrorPtr();
+  ArtMethod* native_method = *self->GetManagedStack()->GetTopQuickFrame();
   bool is_fast = native_method->IsFastNative();
   if (!is_fast) {
     self->TransitionFromSuspendedToRunnable();
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 33d7065..7c92b18 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "art_method-inl.h"
 #include "callee_save_frame.h"
 #include "common_throws.h"
 #include "dex_file-inl.h"
@@ -23,7 +24,6 @@
 #include "gc/accounting/card_table-inl.h"
 #include "interpreter/interpreter.h"
 #include "method_reference.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/method.h"
@@ -279,10 +279,10 @@
   // 'this' object is the 1st argument. They also have the same frame layout as the
   // kRefAndArgs runtime method. Since 'this' is a reference, it is located in the
   // 1st GPR.
-  static mirror::Object* GetProxyThisObject(StackReference<mirror::ArtMethod>* sp)
+  static mirror::Object* GetProxyThisObject(ArtMethod** sp)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    CHECK(sp->AsMirrorPtr()->IsProxyMethod());
-    CHECK_EQ(kQuickCalleeSaveFrame_RefAndArgs_FrameSize, sp->AsMirrorPtr()->GetFrameSizeInBytes());
+    CHECK((*sp)->IsProxyMethod());
+    CHECK_EQ(kQuickCalleeSaveFrame_RefAndArgs_FrameSize, (*sp)->GetFrameSizeInBytes());
     CHECK_GT(kNumQuickGprArgs, 0u);
     constexpr uint32_t kThisGprIndex = 0u;  // 'this' is in the 1st GPR.
     size_t this_arg_offset = kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset +
@@ -291,27 +291,24 @@
     return reinterpret_cast<StackReference<mirror::Object>*>(this_arg_address)->AsMirrorPtr();
   }
 
-  static mirror::ArtMethod* GetCallingMethod(StackReference<mirror::ArtMethod>* sp)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(sp->AsMirrorPtr()->IsCalleeSaveMethod());
+  static ArtMethod* GetCallingMethod(ArtMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    DCHECK((*sp)->IsCalleeSaveMethod());
     return GetCalleeSaveMethodCaller(sp, Runtime::kRefsAndArgs);
   }
 
-  static mirror::ArtMethod* GetOuterMethod(StackReference<mirror::ArtMethod>* sp)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(sp->AsMirrorPtr()->IsCalleeSaveMethod());
+  static ArtMethod* GetOuterMethod(ArtMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    DCHECK((*sp)->IsCalleeSaveMethod());
     uint8_t* previous_sp =
         reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_FrameSize;
-    return reinterpret_cast<StackReference<mirror::ArtMethod>*>(previous_sp)->AsMirrorPtr();
+    return *reinterpret_cast<ArtMethod**>(previous_sp);
   }
 
-  static uint32_t GetCallingDexPc(StackReference<mirror::ArtMethod>* sp)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(sp->AsMirrorPtr()->IsCalleeSaveMethod());
+  static uint32_t GetCallingDexPc(ArtMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    DCHECK((*sp)->IsCalleeSaveMethod());
     const size_t callee_frame_size = GetCalleeSaveFrameSize(kRuntimeISA, Runtime::kRefsAndArgs);
-    auto* caller_sp = reinterpret_cast<StackReference<mirror::ArtMethod>*>(
-          reinterpret_cast<uintptr_t>(sp) + callee_frame_size);
-    mirror::ArtMethod* outer_method = caller_sp->AsMirrorPtr();
+    ArtMethod** caller_sp = reinterpret_cast<ArtMethod**>(
+        reinterpret_cast<uintptr_t>(sp) + callee_frame_size);
+    ArtMethod* outer_method = *caller_sp;
     uintptr_t outer_pc = QuickArgumentVisitor::GetCallingPc(sp);
     uintptr_t outer_pc_offset = outer_method->NativeQuickPcOffset(outer_pc);
 
@@ -331,20 +328,19 @@
   }
 
   // For the given quick ref and args quick frame, return the caller's PC.
-  static uintptr_t GetCallingPc(StackReference<mirror::ArtMethod>* sp)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(sp->AsMirrorPtr()->IsCalleeSaveMethod());
+  static uintptr_t GetCallingPc(ArtMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    DCHECK((*sp)->IsCalleeSaveMethod());
     uint8_t* lr = reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_LrOffset;
     return *reinterpret_cast<uintptr_t*>(lr);
   }
 
-  QuickArgumentVisitor(StackReference<mirror::ArtMethod>* sp, bool is_static, const char* shorty,
+  QuickArgumentVisitor(ArtMethod** sp, bool is_static, const char* shorty,
                        uint32_t shorty_len) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
           is_static_(is_static), shorty_(shorty), shorty_len_(shorty_len),
           gpr_args_(reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset),
           fpr_args_(reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset),
           stack_args_(reinterpret_cast<uint8_t*>(sp) + kQuickCalleeSaveFrame_RefAndArgs_FrameSize
-              + sizeof(StackReference<mirror::ArtMethod>)),  // Skip StackReference<ArtMethod>.
+              + sizeof(ArtMethod*)),  // Skip ArtMethod*.
           gpr_index_(0), fpr_index_(0), fpr_double_index_(0), stack_index_(0),
           cur_type_(Primitive::kPrimVoid), is_split_long_or_double_(false) {
     static_assert(kQuickSoftFloatAbi == (kNumQuickFprArgs == 0),
@@ -355,6 +351,7 @@
     // next register is even.
     static_assert(!kQuickDoubleRegAlignedFloatBackFilled || kNumQuickFprArgs % 2 == 0,
                   "Number of Quick FPR arguments not even");
+    DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
   }
 
   virtual ~QuickArgumentVisitor() {}
@@ -386,7 +383,8 @@
   }
 
   bool IsSplitLongOrDouble() const {
-    if ((GetBytesPerGprSpillLocation(kRuntimeISA) == 4) || (GetBytesPerFprSpillLocation(kRuntimeISA) == 4)) {
+    if ((GetBytesPerGprSpillLocation(kRuntimeISA) == 4) ||
+        (GetBytesPerFprSpillLocation(kRuntimeISA) == 4)) {
       return is_split_long_or_double_;
     } else {
       return false;  // An optimization for when GPR and FPRs are 64bit.
@@ -571,7 +569,7 @@
 
 // Returns the 'this' object of a proxy method. This function is only used by StackVisitor. It
 // allows to use the QuickArgumentVisitor constants without moving all the code in its own module.
-extern "C" mirror::Object* artQuickGetProxyThisObject(StackReference<mirror::ArtMethod>* sp)
+extern "C" mirror::Object* artQuickGetProxyThisObject(ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return QuickArgumentVisitor::GetProxyThisObject(sp);
 }
@@ -579,9 +577,8 @@
 // Visits arguments on the stack placing them into the shadow frame.
 class BuildQuickShadowFrameVisitor FINAL : public QuickArgumentVisitor {
  public:
-  BuildQuickShadowFrameVisitor(StackReference<mirror::ArtMethod>* sp, bool is_static,
-                               const char* shorty, uint32_t shorty_len, ShadowFrame* sf,
-                               size_t first_arg_reg) :
+  BuildQuickShadowFrameVisitor(ArtMethod** sp, bool is_static, const char* shorty,
+                               uint32_t shorty_len, ShadowFrame* sf, size_t first_arg_reg) :
       QuickArgumentVisitor(sp, is_static, shorty, shorty_len), sf_(sf), cur_reg_(first_arg_reg) {}
 
   void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
@@ -626,8 +623,7 @@
   ++cur_reg_;
 }
 
-extern "C" uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Thread* self,
-                                                StackReference<mirror::ArtMethod>* sp)
+extern "C" uint64_t artQuickToInterpreterBridge(ArtMethod* method, Thread* self, ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Ensure we don't get thread suspension until the object arguments are safely in the shadow
   // frame.
@@ -648,7 +644,8 @@
     ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, nullptr, method, 0, memory));
     size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_;
     uint32_t shorty_len = 0;
-    const char* shorty = method->GetShorty(&shorty_len);
+    auto* non_proxy_method = method->GetInterfaceMethodIfProxy(sizeof(void*));
+    const char* shorty = non_proxy_method->GetShorty(&shorty_len);
     BuildQuickShadowFrameVisitor shadow_frame_builder(sp, method->IsStatic(), shorty, shorty_len,
                                                       shadow_frame, first_arg_reg);
     shadow_frame_builder.VisitArguments();
@@ -675,7 +672,7 @@
     self->PopManagedStackFragment(fragment);
 
     // Request a stack deoptimization if needed
-    mirror::ArtMethod* caller = QuickArgumentVisitor::GetCallingMethod(sp);
+    ArtMethod* caller = QuickArgumentVisitor::GetCallingMethod(sp);
     if (UNLIKELY(Dbg::IsForcedInterpreterNeededForUpcall(self, caller))) {
       self->SetException(Thread::GetDeoptimizationException());
       self->SetDeoptimizationReturnValue(result);
@@ -690,8 +687,7 @@
 // to jobjects.
 class BuildQuickArgumentVisitor FINAL : public QuickArgumentVisitor {
  public:
-  BuildQuickArgumentVisitor(StackReference<mirror::ArtMethod>* sp, bool is_static,
-                            const char* shorty, uint32_t shorty_len,
+  BuildQuickArgumentVisitor(ArtMethod** sp, bool is_static, const char* shorty, uint32_t shorty_len,
                             ScopedObjectAccessUnchecked* soa, std::vector<jvalue>* args) :
       QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa), args_(args) {}
 
@@ -754,9 +750,8 @@
 // which is responsible for recording callee save registers. We explicitly place into jobjects the
 // incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
 // field within the proxy object, which will box the primitive arguments and deal with error cases.
-extern "C" uint64_t artQuickProxyInvokeHandler(mirror::ArtMethod* proxy_method,
-                                               mirror::Object* receiver,
-                                               Thread* self, StackReference<mirror::ArtMethod>* sp)
+extern "C" uint64_t artQuickProxyInvokeHandler(
+    ArtMethod* proxy_method, mirror::Object* receiver, Thread* self, ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(proxy_method->IsProxyMethod()) << PrettyMethod(proxy_method);
   DCHECK(receiver->GetClass()->IsProxyClass()) << PrettyMethod(proxy_method);
@@ -764,7 +759,7 @@
   const char* old_cause =
       self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
   // Register the top of the managed stack, making stack crawlable.
-  DCHECK_EQ(sp->AsMirrorPtr(), proxy_method) << PrettyMethod(proxy_method);
+  DCHECK_EQ((*sp), proxy_method) << PrettyMethod(proxy_method);
   DCHECK_EQ(proxy_method->GetFrameSizeInBytes(),
             Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes())
       << PrettyMethod(proxy_method);
@@ -777,12 +772,12 @@
   jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
 
   // Placing arguments into args vector and remove the receiver.
-  mirror::ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy();
+  ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy(sizeof(void*));
   CHECK(!non_proxy_method->IsStatic()) << PrettyMethod(proxy_method) << " "
                                        << PrettyMethod(non_proxy_method);
   std::vector<jvalue> args;
   uint32_t shorty_len = 0;
-  const char* shorty = proxy_method->GetShorty(&shorty_len);
+  const char* shorty = non_proxy_method->GetShorty(&shorty_len);
   BuildQuickArgumentVisitor local_ref_visitor(sp, false, shorty, shorty_len, &soa, &args);
 
   local_ref_visitor.VisitArguments();
@@ -790,7 +785,7 @@
   args.erase(args.begin());
 
   // Convert proxy method into expected interface method.
-  mirror::ArtMethod* interface_method = proxy_method->FindOverriddenMethod();
+  ArtMethod* interface_method = proxy_method->FindOverriddenMethod(sizeof(void*));
   DCHECK(interface_method != nullptr) << PrettyMethod(proxy_method);
   DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
   self->EndAssertNoThreadSuspension(old_cause);
@@ -809,9 +804,8 @@
 // so they don't get garbage collected.
 class RememberForGcArgumentVisitor FINAL : public QuickArgumentVisitor {
  public:
-  RememberForGcArgumentVisitor(StackReference<mirror::ArtMethod>* sp, bool is_static,
-                               const char* shorty, uint32_t shorty_len,
-                               ScopedObjectAccessUnchecked* soa) :
+  RememberForGcArgumentVisitor(ArtMethod** sp, bool is_static, const char* shorty,
+                               uint32_t shorty_len, ScopedObjectAccessUnchecked* soa) :
       QuickArgumentVisitor(sp, is_static, shorty, shorty_len), soa_(soa) {}
 
   void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
@@ -845,10 +839,8 @@
 }
 
 // Lazily resolve a method for quick. Called by stub code.
-extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
-                                                    mirror::Object* receiver,
-                                                    Thread* self,
-                                                    StackReference<mirror::ArtMethod>* sp)
+extern "C" const void* artQuickResolutionTrampoline(
+    ArtMethod* called, mirror::Object* receiver, Thread* self, ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // The resolution trampoline stashes the resolved method into the callee-save frame to transport
   // it. Thus, when exiting, the stack cannot be verified (as the resolved method most likely
@@ -865,7 +857,7 @@
   InvokeType invoke_type;
   MethodReference called_method(nullptr, 0);
   const bool called_method_known_on_entry = !called->IsRuntimeMethod();
-  mirror::ArtMethod* caller = nullptr;
+  ArtMethod* caller = nullptr;
   if (!called_method_known_on_entry) {
     caller = QuickArgumentVisitor::GetCallingMethod(sp);
     uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
@@ -942,7 +934,7 @@
     HandleWrapper<mirror::Object> h_receiver(
         hs.NewHandleWrapper(virtual_or_interface ? &receiver : &dummy));
     DCHECK_EQ(caller->GetDexFile(), called_method.dex_file);
-    called = linker->ResolveMethod(self, called_method.dex_method_index, &caller, invoke_type);
+    called = linker->ResolveMethod(self, called_method.dex_method_index, caller, invoke_type);
   }
   const void* code = nullptr;
   if (LIKELY(!self->IsExceptionPending())) {
@@ -953,11 +945,11 @@
       // Refine called method based on receiver.
       CHECK(receiver != nullptr) << invoke_type;
 
-      mirror::ArtMethod* orig_called = called;
+      ArtMethod* orig_called = called;
       if (invoke_type == kVirtual) {
-        called = receiver->GetClass()->FindVirtualMethodForVirtual(called);
+        called = receiver->GetClass()->FindVirtualMethodForVirtual(called, sizeof(void*));
       } else {
-        called = receiver->GetClass()->FindVirtualMethodForInterface(called);
+        called = receiver->GetClass()->FindVirtualMethodForInterface(called, sizeof(void*));
       }
 
       CHECK(called != nullptr) << PrettyMethod(orig_called) << " "
@@ -983,8 +975,9 @@
                                                      caller_method_name_and_sig_index);
       }
       if ((update_dex_cache_method_index != DexFile::kDexNoIndex) &&
-          (caller->GetDexCacheResolvedMethod(update_dex_cache_method_index) != called)) {
-        caller->SetDexCacheResolvedMethod(update_dex_cache_method_index, called);
+          (caller->GetDexCacheResolvedMethod(
+              update_dex_cache_method_index, sizeof(void*)) != called)) {
+        caller->SetDexCacheResolvedMethod(update_dex_cache_method_index, called, sizeof(void*));
       }
     } else if (invoke_type == kStatic) {
       const auto called_dex_method_idx = called->GetDexMethodIndex();
@@ -994,7 +987,7 @@
       // b/19175856
       if (called->GetDexFile() == called_method.dex_file &&
           called_method.dex_method_index != called_dex_method_idx) {
-        called->GetDexCache()->SetResolvedMethod(called_dex_method_idx, called);
+        called->GetDexCache()->SetResolvedMethod(called_dex_method_idx, called, sizeof(void*));
       }
     }
 
@@ -1043,7 +1036,8 @@
   // Fixup any locally saved objects may have moved during a GC.
   visitor.FixupReferences();
   // Place called method in callee-save frame to be placed as first argument to quick method.
-  sp->Assign(called);
+  *sp = called;
+
   return code;
 }
 
@@ -1523,10 +1517,11 @@
   // is at *m = sp. Will update to point to the bottom of the save frame.
   //
   // Note: assumes ComputeAll() has been run before.
-  void LayoutCalleeSaveFrame(Thread* self, StackReference<mirror::ArtMethod>** m, void* sp,
-                             HandleScope** handle_scope)
+  void LayoutCalleeSaveFrame(Thread* self, ArtMethod*** m, void* sp, HandleScope** handle_scope)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* method = (*m)->AsMirrorPtr();
+    ArtMethod* method = **m;
+
+    DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
 
     uint8_t* sp8 = reinterpret_cast<uint8_t*>(sp);
 
@@ -1538,22 +1533,20 @@
 
     // Under the callee saves put handle scope and new method stack reference.
     size_t handle_scope_size = HandleScope::SizeOf(num_handle_scope_references_);
-    size_t scope_and_method = handle_scope_size + sizeof(StackReference<mirror::ArtMethod>);
+    size_t scope_and_method = handle_scope_size + sizeof(ArtMethod*);
 
     sp8 -= scope_and_method;
     // Align by kStackAlignment.
-    sp8 = reinterpret_cast<uint8_t*>(RoundDown(
-        reinterpret_cast<uintptr_t>(sp8), kStackAlignment));
+    sp8 = reinterpret_cast<uint8_t*>(RoundDown(reinterpret_cast<uintptr_t>(sp8), kStackAlignment));
 
-    uint8_t* sp8_table = sp8 + sizeof(StackReference<mirror::ArtMethod>);
+    uint8_t* sp8_table = sp8 + sizeof(ArtMethod*);
     *handle_scope = HandleScope::Create(sp8_table, self->GetTopHandleScope(),
                                         num_handle_scope_references_);
 
     // Add a slot for the method pointer, and fill it. Fix the pointer-pointer given to us.
     uint8_t* method_pointer = sp8;
-    StackReference<mirror::ArtMethod>* new_method_ref =
-        reinterpret_cast<StackReference<mirror::ArtMethod>*>(method_pointer);
-    new_method_ref->Assign(method);
+    auto** new_method_ref = reinterpret_cast<ArtMethod**>(method_pointer);
+    *new_method_ref = method;
     *m = new_method_ref;
   }
 
@@ -1565,8 +1558,7 @@
 
   // Re-layout the callee-save frame (insert a handle-scope). Then add space for the cookie.
   // Returns the new bottom. Note: this may be unaligned.
-  uint8_t* LayoutJNISaveFrame(Thread* self, StackReference<mirror::ArtMethod>** m, void* sp,
-                              HandleScope** handle_scope)
+  uint8_t* LayoutJNISaveFrame(Thread* self, ArtMethod*** m, void* sp, HandleScope** handle_scope)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // First, fix up the layout of the callee-save frame.
     // We have to squeeze in the HandleScope, and relocate the method pointer.
@@ -1582,9 +1574,9 @@
   }
 
   // WARNING: After this, *sp won't be pointing to the method anymore!
-  uint8_t* ComputeLayout(Thread* self, StackReference<mirror::ArtMethod>** m,
-                         const char* shorty, uint32_t shorty_len, HandleScope** handle_scope,
-                         uintptr_t** start_stack, uintptr_t** start_gpr, uint32_t** start_fpr)
+  uint8_t* ComputeLayout(Thread* self, ArtMethod*** m, const char* shorty, uint32_t shorty_len,
+                         HandleScope** handle_scope, uintptr_t** start_stack, uintptr_t** start_gpr,
+                         uint32_t** start_fpr)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Walk(shorty, shorty_len);
 
@@ -1673,7 +1665,7 @@
 class BuildGenericJniFrameVisitor FINAL : public QuickArgumentVisitor {
  public:
   BuildGenericJniFrameVisitor(Thread* self, bool is_static, const char* shorty, uint32_t shorty_len,
-                              StackReference<mirror::ArtMethod>** sp)
+                              ArtMethod*** sp)
      : QuickArgumentVisitor(*sp, is_static, shorty, shorty_len),
        jni_call_(nullptr, nullptr, nullptr, nullptr), sm_(&jni_call_) {
     ComputeGenericJniFrameSize fsc;
@@ -1691,7 +1683,7 @@
     sm_.AdvancePointer(self->GetJniEnv());
 
     if (is_static) {
-      sm_.AdvanceHandleScope((*sp)->AsMirrorPtr()->GetDeclaringClass());
+      sm_.AdvanceHandleScope((**sp)->GetDeclaringClass());
     }
   }
 
@@ -1847,10 +1839,9 @@
  * 1) How many bytes of the alloca can be released, if the value is non-negative.
  * 2) An error, if the value is negative.
  */
-extern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self,
-                                                      StackReference<mirror::ArtMethod>* sp)
+extern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self, ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ArtMethod* called = sp->AsMirrorPtr();
+  ArtMethod* called = *sp;
   DCHECK(called->IsNative()) << PrettyMethod(called, true);
   uint32_t shorty_len = 0;
   const char* shorty = called->GetShorty(&shorty_len);
@@ -1923,15 +1914,15 @@
  */
 extern "C" uint64_t artQuickGenericJniEndTrampoline(Thread* self, jvalue result, uint64_t result_f)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  StackReference<mirror::ArtMethod>* sp = self->GetManagedStack()->GetTopQuickFrame();
+  ArtMethod** sp = self->GetManagedStack()->GetTopQuickFrame();
   uint32_t* sp32 = reinterpret_cast<uint32_t*>(sp);
-  mirror::ArtMethod* called = sp->AsMirrorPtr();
+  ArtMethod* called = *sp;
   uint32_t cookie = *(sp32 - 1);
 
   jobject lock = nullptr;
   if (called->IsSynchronized()) {
     HandleScope* table = reinterpret_cast<HandleScope*>(reinterpret_cast<uint8_t*>(sp)
-        + sizeof(StackReference<mirror::ArtMethod>));
+        + sizeof(*sp));
     lock = table->GetHandle(0).ToJObject();
   }
 
@@ -1982,15 +1973,12 @@
 // to hold the mutator lock (see SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) annotations).
 
 template<InvokeType type, bool access_check>
-static TwoWordReturn artInvokeCommon(uint32_t method_idx,
-                                     mirror::Object* this_object,
-                                     Thread* self,
-                                     StackReference<mirror::ArtMethod>* sp) {
+static TwoWordReturn artInvokeCommon(uint32_t method_idx, mirror::Object* this_object, Thread* self,
+                                     ArtMethod** sp) {
   ScopedQuickEntrypointChecks sqec(self);
-  DCHECK_EQ(sp->AsMirrorPtr(), Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs));
-  mirror::ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
-  mirror::ArtMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check,
-                                             type);
+  DCHECK_EQ(*sp, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs));
+  ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
+  ArtMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
   if (UNLIKELY(method == nullptr)) {
     const DexFile* dex_file = caller_method->GetDeclaringClass()->GetDexCache()->GetDexFile();
     uint32_t shorty_len;
@@ -2025,10 +2013,8 @@
 // Explicit artInvokeCommon template function declarations to please analysis tool.
 #define EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(type, access_check)                                \
   template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)                                          \
-  TwoWordReturn artInvokeCommon<type, access_check>(uint32_t method_idx,                        \
-                                                    mirror::Object* this_object,                \
-                                                    Thread* self,                               \
-                                                    StackReference<mirror::ArtMethod>* sp)      \
+  TwoWordReturn artInvokeCommon<type, access_check>(                                            \
+      uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp)
 
 EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kVirtual, false);
 EXPLICIT_INVOKE_COMMON_TEMPLATE_DECL(kVirtual, true);
@@ -2044,69 +2030,56 @@
 
 // See comments in runtime_support_asm.S
 extern "C" TwoWordReturn artInvokeInterfaceTrampolineWithAccessCheck(
-    uint32_t method_idx,
-    mirror::Object* this_object,
-    Thread* self,
-    StackReference<mirror::ArtMethod>* sp)
-        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon<kInterface, true>(method_idx, this_object, self, sp);
 }
 
 extern "C" TwoWordReturn artInvokeDirectTrampolineWithAccessCheck(
-    uint32_t method_idx,
-    mirror::Object* this_object,
-    Thread* self,
-    StackReference<mirror::ArtMethod>* sp)
-        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon<kDirect, true>(method_idx, this_object, self, sp);
 }
 
 extern "C" TwoWordReturn artInvokeStaticTrampolineWithAccessCheck(
-    uint32_t method_idx,
-    mirror::Object* this_object,
-    Thread* self,
-    StackReference<mirror::ArtMethod>* sp)
-        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon<kStatic, true>(method_idx, this_object, self, sp);
 }
 
 extern "C" TwoWordReturn artInvokeSuperTrampolineWithAccessCheck(
-    uint32_t method_idx,
-    mirror::Object* this_object,
-    Thread* self,
-    StackReference<mirror::ArtMethod>* sp)
-        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon<kSuper, true>(method_idx, this_object, self, sp);
 }
 
 extern "C" TwoWordReturn artInvokeVirtualTrampolineWithAccessCheck(
-    uint32_t method_idx,
-    mirror::Object* this_object,
-    Thread* self,
-    StackReference<mirror::ArtMethod>* sp)
-        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    uint32_t method_idx, mirror::Object* this_object, Thread* self, ArtMethod** sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return artInvokeCommon<kVirtual, true>(method_idx, this_object, self, sp);
 }
 
 // Determine target of interface dispatch. This object is known non-null.
 extern "C" TwoWordReturn artInvokeInterfaceTrampoline(uint32_t dex_method_idx,
                                                       mirror::Object* this_object,
-                                                      Thread* self,
-                                                      StackReference<mirror::ArtMethod>* sp)
+                                                      Thread* self, ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   // The optimizing compiler currently does not inline methods that have an interface
   // invocation. We use the outer method directly to avoid fetching a stack map, which is
   // more expensive.
-  mirror::ArtMethod* caller_method = QuickArgumentVisitor::GetOuterMethod(sp);
+  ArtMethod* caller_method = QuickArgumentVisitor::GetOuterMethod(sp);
   DCHECK_EQ(caller_method, QuickArgumentVisitor::GetCallingMethod(sp));
-  mirror::ArtMethod* interface_method = caller_method->GetDexCacheResolvedMethod(dex_method_idx);
-  mirror::ArtMethod* method;
+  ArtMethod* interface_method = caller_method->GetDexCacheResolvedMethod(
+      dex_method_idx, sizeof(void*));
+  DCHECK(interface_method != nullptr) << dex_method_idx << " " << PrettyMethod(caller_method);
+  ArtMethod* method;
   if (LIKELY(interface_method->GetDexMethodIndex() != DexFile::kDexNoIndex)) {
-    method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
+    method = this_object->GetClass()->FindVirtualMethodForInterface(
+        interface_method, sizeof(void*));
     if (UNLIKELY(method == nullptr)) {
-      ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(interface_method, this_object,
-                                                                 caller_method);
+      ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(
+          interface_method, this_object, caller_method);
       return GetTwoWordFailureValue();  // Failure.
     }
   } else {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc
index 01c17ac..5cdf967 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc
@@ -16,9 +16,9 @@
 
 #include <stdint.h>
 
+#include "art_method-inl.h"
 #include "callee_save_frame.h"
 #include "common_runtime_test.h"
-#include "mirror/art_method-inl.h"
 #include "quick/quick_method_frame_info.h"
 
 namespace art {
@@ -31,8 +31,7 @@
     options->push_back(std::make_pair("imageinstructionset", "x86_64"));
   }
 
-  static mirror::ArtMethod* CreateCalleeSaveMethod(InstructionSet isa,
-                                                   Runtime::CalleeSaveType type)
+  static ArtMethod* CreateCalleeSaveMethod(InstructionSet isa, Runtime::CalleeSaveType type)
       NO_THREAD_SAFETY_ANALYSIS {
     Runtime* r = Runtime::Current();
 
@@ -40,7 +39,7 @@
     t->TransitionFromSuspendedToRunnable();  // So we can create callee-save methods.
 
     r->SetInstructionSet(isa);
-    mirror::ArtMethod* save_method = r->CreateCalleeSaveMethod();
+    ArtMethod* save_method = r->CreateCalleeSaveMethod();
     r->SetCalleeSaveMethod(save_method, type);
 
     t->TransitionFromRunnableToSuspended(ThreadState::kNative);  // So we can shut down.
@@ -50,7 +49,7 @@
 
   static void CheckFrameSize(InstructionSet isa, Runtime::CalleeSaveType type, uint32_t save_size)
       NO_THREAD_SAFETY_ANALYSIS {
-    mirror::ArtMethod* save_method = CreateCalleeSaveMethod(isa, type);
+    ArtMethod* save_method = CreateCalleeSaveMethod(isa, type);
     QuickMethodFrameInfo frame_info = save_method->GetQuickFrameInfo();
     EXPECT_EQ(frame_info.FrameSizeInBytes(), save_size) << "Expected and real size differs for "
         << type << " core spills=" << std::hex << frame_info.CoreSpillMask() << " fp spills="
@@ -59,7 +58,7 @@
 
   static void CheckPCOffset(InstructionSet isa, Runtime::CalleeSaveType type, size_t pc_offset)
       NO_THREAD_SAFETY_ANALYSIS {
-    mirror::ArtMethod* save_method = CreateCalleeSaveMethod(isa, type);
+    ArtMethod* save_method = CreateCalleeSaveMethod(isa, type);
     QuickMethodFrameInfo frame_info = save_method->GetQuickFrameInfo();
     EXPECT_EQ(save_method->GetReturnPcOffset().SizeValue(), pc_offset)
         << "Expected and real pc offset differs for " << type
diff --git a/runtime/entrypoints/runtime_asm_entrypoints.h b/runtime/entrypoints/runtime_asm_entrypoints.h
index bfe7ee8..8209dc8 100644
--- a/runtime/entrypoints/runtime_asm_entrypoints.h
+++ b/runtime/entrypoints/runtime_asm_entrypoints.h
@@ -29,19 +29,19 @@
 }
 
 // Return the address of quick stub code for handling IMT conflicts.
-extern "C" void art_quick_imt_conflict_trampoline(mirror::ArtMethod*);
+extern "C" void art_quick_imt_conflict_trampoline(ArtMethod*);
 static inline const void* GetQuickImtConflictStub() {
   return reinterpret_cast<const void*>(art_quick_imt_conflict_trampoline);
 }
 
 // Return the address of quick stub code for bridging from quick code to the interpreter.
-extern "C" void art_quick_to_interpreter_bridge(mirror::ArtMethod*);
+extern "C" void art_quick_to_interpreter_bridge(ArtMethod*);
 static inline const void* GetQuickToInterpreterBridge() {
   return reinterpret_cast<const void*>(art_quick_to_interpreter_bridge);
 }
 
 // Return the address of quick stub code for handling JNI calls.
-extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
+extern "C" void art_quick_generic_jni_trampoline(ArtMethod*);
 static inline const void* GetQuickGenericJniStub() {
   return reinterpret_cast<const void*>(art_quick_generic_jni_trampoline);
 }
@@ -53,7 +53,7 @@
 }
 
 // Return the address of quick stub code for resolving a method at first call.
-extern "C" void art_quick_resolution_trampoline(mirror::ArtMethod*);
+extern "C" void art_quick_resolution_trampoline(ArtMethod*);
 static inline const void* GetQuickResolutionStub() {
   return reinterpret_cast<const void*>(art_quick_resolution_trampoline);
 }
diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc
index 6808000..bc3ba21 100644
--- a/runtime/exception_test.cc
+++ b/runtime/exception_test.cc
@@ -96,11 +96,11 @@
     CHECK_EQ(mapping_table_offset & 1u, 0u);
     const uint8_t* code_ptr = &fake_header_code_and_maps_[gc_map_offset];
 
-    method_f_ = my_klass_->FindVirtualMethod("f", "()I");
+    method_f_ = my_klass_->FindVirtualMethod("f", "()I", sizeof(void*));
     ASSERT_TRUE(method_f_ != nullptr);
     method_f_->SetEntryPointFromQuickCompiledCode(code_ptr);
 
-    method_g_ = my_klass_->FindVirtualMethod("g", "(I)V");
+    method_g_ = my_klass_->FindVirtualMethod("g", "(I)V", sizeof(void*));
     ASSERT_TRUE(method_g_ != nullptr);
     method_g_->SetEntryPointFromQuickCompiledCode(code_ptr);
   }
@@ -113,8 +113,8 @@
   std::vector<uint8_t> fake_gc_map_;
   std::vector<uint8_t> fake_header_code_and_maps_;
 
-  mirror::ArtMethod* method_f_;
-  mirror::ArtMethod* method_g_;
+  ArtMethod* method_f_;
+  ArtMethod* method_g_;
 
  private:
   mirror::Class* my_klass_;
@@ -167,7 +167,7 @@
   std::vector<uintptr_t> fake_stack;
   Runtime* r = Runtime::Current();
   r->SetInstructionSet(kRuntimeISA);
-  mirror::ArtMethod* save_method = r->CreateCalleeSaveMethod();
+  ArtMethod* save_method = r->CreateCalleeSaveMethod();
   r->SetCalleeSaveMethod(save_method, Runtime::kSaveAll);
   QuickMethodFrameInfo frame_info = save_method->GetQuickFrameInfo();
 
@@ -209,14 +209,13 @@
   fake_stack.push_back(0);
 
   // Set up thread to appear as if we called out of method_g_ at pc dex 3
-  thread->SetTopOfStack(reinterpret_cast<StackReference<mirror::ArtMethod>*>(&fake_stack[0]));
+  thread->SetTopOfStack(reinterpret_cast<ArtMethod**>(&fake_stack[0]));
 
   jobject internal = thread->CreateInternalStackTrace<false>(soa);
   ASSERT_TRUE(internal != nullptr);
   jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(soa, internal);
   ASSERT_TRUE(ste_array != nullptr);
-  mirror::ObjectArray<mirror::StackTraceElement>* trace_array =
-      soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(ste_array);
+  auto* trace_array = soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(ste_array);
 
   ASSERT_TRUE(trace_array != nullptr);
   ASSERT_TRUE(trace_array->Get(0) != nullptr);
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index 83f3ae1..4a352dd 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -19,8 +19,9 @@
 #include <setjmp.h>
 #include <sys/mman.h>
 #include <sys/ucontext.h>
+
+#include "art_method-inl.h"
 #include "base/stl_util.h"
-#include "mirror/art_method.h"
 #include "mirror/class.h"
 #include "sigchain.h"
 #include "thread-inl.h"
@@ -321,7 +322,7 @@
     return false;
   }
 
-  mirror::ArtMethod* method_obj = 0;
+  ArtMethod* method_obj = 0;
   uintptr_t return_pc = 0;
   uintptr_t sp = 0;
 
@@ -331,6 +332,7 @@
 
   // If we don't have a potential method, we're outta here.
   VLOG(signals) << "potential method: " << method_obj;
+  // TODO: Check linear alloc and image.
   if (method_obj == 0 || !IsAligned<kObjectAlignment>(method_obj)) {
     VLOG(signals) << "no method";
     return false;
@@ -341,7 +343,7 @@
   // Check that the class pointer inside the object is not null and is aligned.
   // TODO: Method might be not a heap address, and GetClass could fault.
   // No read barrier because method_obj may not be a real object.
-  mirror::Class* cls = method_obj->GetClass<kVerifyNone, kWithoutReadBarrier>();
+  mirror::Class* cls = method_obj->GetDeclaringClassNoBarrier();
   if (cls == nullptr) {
     VLOG(signals) << "not a class";
     return false;
@@ -357,12 +359,6 @@
     return false;
   }
 
-  // Now make sure the class is a mirror::ArtMethod.
-  if (!cls->IsArtMethodClass()) {
-    VLOG(signals) << "not a method";
-    return false;
-  }
-
   // We can be certain that this is a method now.  Check if we have a GC map
   // at the return PC address.
   if (true || kIsDebugBuild) {
@@ -418,16 +414,14 @@
 #endif
   if (in_generated_code) {
     LOG(ERROR) << "Dumping java stack trace for crash in generated code";
-    mirror::ArtMethod* method = nullptr;
+    ArtMethod* method = nullptr;
     uintptr_t return_pc = 0;
     uintptr_t sp = 0;
     Thread* self = Thread::Current();
 
     manager_->GetMethodAndReturnPcAndSp(siginfo, context, &method, &return_pc, &sp);
     // Inside of generated code, sp[0] is the method, so sp is the frame.
-    StackReference<mirror::ArtMethod>* frame =
-        reinterpret_cast<StackReference<mirror::ArtMethod>*>(sp);
-    self->SetTopOfStack(frame);
+    self->SetTopOfStack(reinterpret_cast<ArtMethod**>(sp));
 #ifdef TEST_NESTED_SIGNAL
     // To test the nested signal handler we raise a signal here.  This will cause the
     // nested signal handler to be called and perform a longjmp back to the setjmp
diff --git a/runtime/fault_handler.h b/runtime/fault_handler.h
index adac4c2..3b03a14 100644
--- a/runtime/fault_handler.h
+++ b/runtime/fault_handler.h
@@ -27,10 +27,7 @@
 
 namespace art {
 
-namespace mirror {
 class ArtMethod;
-}  // namespace mirror
-
 class FaultHandler;
 
 class FaultManager {
@@ -58,7 +55,7 @@
   // The IsInGeneratedCode() function checks that the mutator lock is held before it
   // calls GetMethodAndReturnPCAndSP().
   // TODO: think about adding lock assertions and fake lock and unlock functions.
-  void GetMethodAndReturnPcAndSp(siginfo_t* siginfo, void* context, mirror::ArtMethod** out_method,
+  void GetMethodAndReturnPcAndSp(siginfo_t* siginfo, void* context, ArtMethod** out_method,
                                  uintptr_t* out_return_pc, uintptr_t* out_sp)
                                  NO_THREAD_SAFETY_ANALYSIS;
   bool IsInGeneratedCode(siginfo_t* siginfo, void *context, bool check_dex_pc)
diff --git a/runtime/gc/accounting/mod_union_table_test.cc b/runtime/gc/accounting/mod_union_table_test.cc
index 043b558..363b76a 100644
--- a/runtime/gc/accounting/mod_union_table_test.cc
+++ b/runtime/gc/accounting/mod_union_table_test.cc
@@ -198,12 +198,12 @@
   obj1->Set(1, other_space_ref1);
   obj2->Set(3, other_space_ref2);
   table->ClearCards();
-  std::set<mirror::Object*> visited;
-  table->UpdateAndMarkReferences(&CollectVisitedCallback, &visited);
+  std::set<mirror::Object*> visited_before;
+  table->UpdateAndMarkReferences(&CollectVisitedCallback, &visited_before);
   // Check that we visited all the references in other spaces only.
-  ASSERT_GE(visited.size(), 2u);
-  ASSERT_TRUE(visited.find(other_space_ref1) != visited.end());
-  ASSERT_TRUE(visited.find(other_space_ref2) != visited.end());
+  ASSERT_GE(visited_before.size(), 2u);
+  ASSERT_TRUE(visited_before.find(other_space_ref1) != visited_before.end());
+  ASSERT_TRUE(visited_before.find(other_space_ref2) != visited_before.end());
   // Verify that all the other references were visited.
   // obj1, obj2 cards should still be in mod union table since they have references to other
   // spaces.
@@ -229,12 +229,15 @@
     ASSERT_TRUE(table->ContainsCardFor(reinterpret_cast<uintptr_t>(ptr)));
   }
   // Visit again and make sure the cards got cleared back to their sane state.
-  visited.clear();
-  table->UpdateAndMarkReferences(&CollectVisitedCallback, &visited);
-  // Verify that the dump matches what we saw earlier.
+  std::set<mirror::Object*> visited_after;
+  table->UpdateAndMarkReferences(&CollectVisitedCallback, &visited_after);
+  // Check that we visited a superset after.
+  for (auto* obj : visited_before) {
+    ASSERT_TRUE(visited_after.find(obj) != visited_after.end()) << obj;
+  }
+  // Verify that the dump still works.
   std::ostringstream oss2;
   table->Dump(oss2);
-  ASSERT_EQ(oss.str(), oss2.str());
   // Remove the space we added so it doesn't persist to the next test.
   heap->RemoveSpace(other_space.get());
 }
diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc
index 84dadea..fe2b284 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -21,7 +21,7 @@
 #include "dex_file-inl.h"
 #include "mem_map.h"
 #include "mirror/object-inl.h"
-#include "mirror/class.h"
+#include "mirror/class-inl.h"
 #include "mirror/object_array.h"
 
 namespace art {
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index 26f349a..658390d 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -22,6 +22,7 @@
 #include "gc/space/image_space.h"
 #include "gc/space/space.h"
 #include "intern_table.h"
+#include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "scoped_thread_state_change.h"
 #include "thread-inl.h"
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 2a9c03d..91a0e8a 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -401,7 +401,8 @@
                             << (field != nullptr ? field->GetTypeDescriptor() : "")
                             << " first_ref_field_offset="
                             << (holder_->IsClass()
-                                ? holder_->AsClass()->GetFirstReferenceStaticFieldOffset()
+                                ? holder_->AsClass()->GetFirstReferenceStaticFieldOffset(
+                                    sizeof(void*))
                                 : holder_->GetClass()->GetFirstReferenceInstanceFieldOffset())
                             << " num_of_ref_fields="
                             << (holder_->IsClass()
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index eb0e9be..2d54330 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -30,7 +30,6 @@
 #include "gc/space/rosalloc_space-inl.h"
 #include "runtime.h"
 #include "handle_scope-inl.h"
-#include "thread.h"
 #include "thread-inl.h"
 #include "utils.h"
 #include "verify_object-inl.h"
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index 5af2a53..4d51d38 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -17,8 +17,8 @@
 #include "reference_processor.h"
 
 #include "base/time_utils.h"
+#include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
-#include "mirror/reference.h"
 #include "mirror/reference-inl.h"
 #include "reference_processor-inl.h"
 #include "reflection.h"
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index ade9cec0..437fd8c 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -23,13 +23,13 @@
 
 #include <random>
 
+#include "art_method.h"
 #include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/scoped_flock.h"
 #include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "gc/accounting/space_bitmap-inl.h"
-#include "mirror/art_method.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "oat_file.h"
@@ -687,7 +687,20 @@
                               image_file_size, image_header.GetImageSize());
     return nullptr;
   }
-  auto end_of_bitmap = image_header.GetImageBitmapOffset() + image_header.GetImageBitmapSize();
+
+  if (kIsDebugBuild) {
+    LOG(INFO) << "Dumping image sections";
+    for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
+      const auto section_idx = static_cast<ImageHeader::ImageSections>(i);
+      auto& section = image_header.GetImageSection(section_idx);
+      LOG(INFO) << section_idx << " start="
+          << reinterpret_cast<void*>(image_header.GetImageBegin() + section.Offset())
+          << section;
+    }
+  }
+
+  const auto& bitmap_section = image_header.GetImageSection(ImageHeader::kSectionImageBitmap);
+  auto end_of_bitmap = static_cast<size_t>(bitmap_section.End());
   if (end_of_bitmap != image_file_size) {
     *error_msg = StringPrintf(
         "Image file size does not equal end of bitmap: size=%" PRIu64 " vs. %zu.", image_file_size,
@@ -697,7 +710,7 @@
 
   // Note: The image header is part of the image due to mmap page alignment required of offset.
   std::unique_ptr<MemMap> map(MemMap::MapFileAtAddress(
-      image_header.GetImageBegin(), image_header.GetImageSize() + image_header.GetArtFieldsSize(),
+      image_header.GetImageBegin(), image_header.GetImageSize(),
       PROT_READ | PROT_WRITE, MAP_PRIVATE, file->Fd(), 0, false, image_filename, error_msg));
   if (map.get() == nullptr) {
     DCHECK(!error_msg->empty());
@@ -706,13 +719,9 @@
   CHECK_EQ(image_header.GetImageBegin(), map->Begin());
   DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader)));
 
-  std::unique_ptr<MemMap> image_map(
-      MemMap::MapFileAtAddress(nullptr, image_header.GetImageBitmapSize(),
-                               PROT_READ, MAP_PRIVATE,
-                               file->Fd(), image_header.GetImageBitmapOffset(),
-                               false,
-                               image_filename,
-                               error_msg));
+  std::unique_ptr<MemMap> image_map(MemMap::MapFileAtAddress(
+      nullptr, bitmap_section.Size(), PROT_READ, MAP_PRIVATE, file->Fd(),
+      bitmap_section.Offset(), false, image_filename, error_msg));
   if (image_map.get() == nullptr) {
     *error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str());
     return nullptr;
@@ -729,7 +738,9 @@
     return nullptr;
   }
 
-  uint8_t* const image_end = map->Begin() + image_header.GetImageSize();
+  // We only want the mirror object, not the ArtFields and ArtMethods.
+  uint8_t* const image_end =
+      map->Begin() + image_header.GetImageSection(ImageHeader::kSectionObjects).End();
   std::unique_ptr<ImageSpace> space(new ImageSpace(image_filename, image_location,
                                                    map.release(), bitmap.release(), image_end));
 
@@ -753,25 +764,16 @@
   Runtime* runtime = Runtime::Current();
   runtime->SetInstructionSet(space->oat_file_->GetOatHeader().GetInstructionSet());
 
-  mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
-  runtime->SetResolutionMethod(down_cast<mirror::ArtMethod*>(resolution_method));
-  mirror::Object* imt_conflict_method = image_header.GetImageRoot(ImageHeader::kImtConflictMethod);
-  runtime->SetImtConflictMethod(down_cast<mirror::ArtMethod*>(imt_conflict_method));
-  mirror::Object* imt_unimplemented_method =
-      image_header.GetImageRoot(ImageHeader::kImtUnimplementedMethod);
-  runtime->SetImtUnimplementedMethod(down_cast<mirror::ArtMethod*>(imt_unimplemented_method));
-  mirror::Object* default_imt = image_header.GetImageRoot(ImageHeader::kDefaultImt);
-  runtime->SetDefaultImt(down_cast<mirror::ObjectArray<mirror::ArtMethod>*>(default_imt));
-
-  mirror::Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod);
-  runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method),
-                               Runtime::kSaveAll);
-  callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsOnlySaveMethod);
-  runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method),
-                               Runtime::kRefsOnly);
-  callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod);
-  runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method),
-                               Runtime::kRefsAndArgs);
+  runtime->SetResolutionMethod(image_header.GetImageMethod(ImageHeader::kResolutionMethod));
+  runtime->SetImtConflictMethod(image_header.GetImageMethod(ImageHeader::kImtConflictMethod));
+  runtime->SetImtUnimplementedMethod(
+      image_header.GetImageMethod(ImageHeader::kImtUnimplementedMethod));
+  runtime->SetCalleeSaveMethod(
+      image_header.GetImageMethod(ImageHeader::kCalleeSaveMethod), Runtime::kSaveAll);
+  runtime->SetCalleeSaveMethod(
+      image_header.GetImageMethod(ImageHeader::kRefsOnlySaveMethod), Runtime::kRefsOnly);
+  runtime->SetCalleeSaveMethod(
+      image_header.GetImageMethod(ImageHeader::kRefsAndArgsSaveMethod), Runtime::kRefsAndArgs);
 
   if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
     LOG(INFO) << "ImageSpace::Init exiting (" << PrettyDuration(NanoTime() - start_time)
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index 3e9e9f7..6e0e0d2 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -23,6 +23,8 @@
 #include "common_runtime_test.h"
 #include "globals.h"
 #include "mirror/array-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
 #include "scoped_thread_state_change.h"
 #include "zygote_space.h"
diff --git a/runtime/globals.h b/runtime/globals.h
index 4d7fd2e..fe699c6 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -67,12 +67,8 @@
 // Garbage collector constants.
 static constexpr bool kMovingCollector = true;
 static constexpr bool kMarkCompactSupport = false && kMovingCollector;
-// True if we allow moving field arrays, this can cause complication with mark compact.
-static constexpr bool kMoveFieldArrays = !kMarkCompactSupport;
 // True if we allow moving classes.
 static constexpr bool kMovingClasses = !kMarkCompactSupport;
-// True if we allow moving methods.
-static constexpr bool kMovingMethods = false;
 
 // If true, the quick compiler embeds class pointers in the compiled
 // code, if possible.
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index ac28c8a..9a0e52e 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -159,6 +159,10 @@
   ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  Thread* Self() const {
+    return self_;
+  }
+
  private:
   template<class T>
   ALWAYS_INLINE MutableHandle<T> GetHandle(size_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/image.cc b/runtime/image.cc
index d9bd2a8..947c914 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -24,27 +24,21 @@
 namespace art {
 
 const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '1', '5', '\0' };
+const uint8_t ImageHeader::kImageVersion[] = { '0', '1', '6', '\0' };
 
 ImageHeader::ImageHeader(uint32_t image_begin,
                          uint32_t image_size,
-                         uint32_t art_fields_offset,
-                         uint32_t art_fields_size,
-                         uint32_t image_bitmap_offset,
-                         uint32_t image_bitmap_size,
+                         ImageSection* sections,
                          uint32_t image_roots,
                          uint32_t oat_checksum,
                          uint32_t oat_file_begin,
                          uint32_t oat_data_begin,
                          uint32_t oat_data_end,
                          uint32_t oat_file_end,
+                         uint32_t pointer_size,
                          bool compile_pic)
   : image_begin_(image_begin),
     image_size_(image_size),
-    art_fields_offset_(art_fields_offset),
-    art_fields_size_(art_fields_size),
-    image_bitmap_offset_(image_bitmap_offset),
-    image_bitmap_size_(image_bitmap_size),
     oat_checksum_(oat_checksum),
     oat_file_begin_(oat_file_begin),
     oat_data_begin_(oat_data_begin),
@@ -52,6 +46,7 @@
     oat_file_end_(oat_file_end),
     patch_delta_(0),
     image_roots_(image_roots),
+    pointer_size_(pointer_size),
     compile_pic_(compile_pic) {
   CHECK_EQ(image_begin, RoundUp(image_begin, kPageSize));
   CHECK_EQ(oat_file_begin, RoundUp(oat_file_begin, kPageSize));
@@ -61,8 +56,10 @@
   CHECK_LE(oat_file_begin, oat_data_begin);
   CHECK_LT(oat_data_begin, oat_data_end);
   CHECK_LE(oat_data_end, oat_file_end);
+  CHECK(ValidPointerSize(pointer_size_)) << pointer_size_;
   memcpy(magic_, kImageMagic, sizeof(kImageMagic));
   memcpy(version_, kImageVersion, sizeof(kImageVersion));
+  std::copy_n(sections, kSectionCount, sections_);
 }
 
 void ImageHeader::RelocateImage(off_t delta) {
@@ -74,6 +71,9 @@
   oat_file_end_ += delta;
   image_roots_ += delta;
   patch_delta_ += delta;
+  for (size_t i = 0; i < kImageMethodsCount; ++i) {
+    image_methods_[i] += delta;
+  }
 }
 
 bool ImageHeader::IsValid() const {
@@ -128,4 +128,23 @@
   return result;
 }
 
+ArtMethod* ImageHeader::GetImageMethod(ImageMethod index) const {
+  CHECK_LT(static_cast<size_t>(index), kImageMethodsCount);
+  return reinterpret_cast<ArtMethod*>(image_methods_[index]);
+}
+
+void ImageHeader::SetImageMethod(ImageMethod index, ArtMethod* method) {
+  CHECK_LT(static_cast<size_t>(index), kImageMethodsCount);
+  image_methods_[index] = reinterpret_cast<uint64_t>(method);
+}
+
+const ImageSection& ImageHeader::GetImageSection(ImageSections index) const {
+  CHECK_LT(static_cast<size_t>(index), kSectionCount);
+  return sections_[index];
+}
+
+std::ostream& operator<<(std::ostream& os, const ImageSection& section) {
+  return os << "size=" << section.Size() << " range=" << section.Offset() << "-" << section.End();
+}
+
 }  // namespace art
diff --git a/runtime/image.h b/runtime/image.h
index 52995ed..c6be7ef 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -24,6 +24,34 @@
 
 namespace art {
 
+class PACKED(4) ImageSection {
+ public:
+  ImageSection() : offset_(0), size_(0) { }
+  ImageSection(uint32_t offset, uint32_t size) : offset_(offset), size_(size) { }
+  ImageSection(const ImageSection& section) = default;
+  ImageSection& operator=(const ImageSection& section) = default;
+
+  uint32_t Offset() const {
+    return offset_;
+  }
+
+  uint32_t Size() const {
+    return size_;
+  }
+
+  uint32_t End() const {
+    return Offset() + Size();
+  }
+
+  bool Contains(uint64_t offset) const {
+    return offset - offset_ < size_;
+  }
+
+ private:
+  uint32_t offset_;
+  uint32_t size_;
+};
+
 // header of image files written by ImageWriter, read and validated by Space.
 class PACKED(4) ImageHeader {
  public:
@@ -31,16 +59,14 @@
 
   ImageHeader(uint32_t image_begin,
               uint32_t image_size_,
-              uint32_t art_fields_offset,
-              uint32_t art_fields_size,
-              uint32_t image_bitmap_offset,
-              uint32_t image_bitmap_size,
+              ImageSection* sections,
               uint32_t image_roots,
               uint32_t oat_checksum,
               uint32_t oat_file_begin,
               uint32_t oat_data_begin,
               uint32_t oat_data_end,
               uint32_t oat_file_end,
+              uint32_t pointer_size,
               bool compile_pic_);
 
   bool IsValid() const;
@@ -54,22 +80,6 @@
     return static_cast<uint32_t>(image_size_);
   }
 
-  size_t GetArtFieldsOffset() const {
-    return art_fields_offset_;
-  }
-
-  size_t GetArtFieldsSize() const {
-    return art_fields_size_;
-  }
-
-  size_t GetImageBitmapOffset() const {
-    return image_bitmap_offset_;
-  }
-
-  size_t GetImageBitmapSize() const {
-    return image_bitmap_size_;
-  }
-
   uint32_t GetOatChecksum() const {
     return oat_checksum_;
   }
@@ -94,6 +104,10 @@
     return reinterpret_cast<uint8_t*>(oat_file_end_);
   }
 
+  uint32_t GetPointerSize() const {
+    return pointer_size_;
+  }
+
   off_t GetPatchDelta() const {
     return patch_delta_;
   }
@@ -108,19 +122,38 @@
     return oat_filename;
   }
 
-  enum ImageRoot {
+  enum ImageMethod {
     kResolutionMethod,
     kImtConflictMethod,
     kImtUnimplementedMethod,
-    kDefaultImt,
     kCalleeSaveMethod,
     kRefsOnlySaveMethod,
     kRefsAndArgsSaveMethod,
+    kImageMethodsCount,  // Number of elements in enum.
+  };
+
+  enum ImageRoot {
     kDexCaches,
     kClassRoots,
     kImageRootsMax,
   };
 
+  enum ImageSections {
+    kSectionObjects,
+    kSectionArtFields,
+    kSectionArtMethods,
+    kSectionImageBitmap,
+    kSectionCount,  // Number of elements in enum.
+  };
+
+  ArtMethod* GetImageMethod(ImageMethod index) const;
+  void SetImageMethod(ImageMethod index, ArtMethod* method);
+
+  const ImageSection& GetImageSection(ImageSections index) const;
+  const ImageSection& GetMethodsSection() const {
+    return GetImageSection(kSectionArtMethods);
+  }
+
   mirror::Object* GetImageRoot(ImageRoot image_root) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::ObjectArray<mirror::Object>* GetImageRoots() const
@@ -145,18 +178,6 @@
   // Image size, not page aligned.
   uint32_t image_size_;
 
-  // ArtField array offset.
-  uint32_t art_fields_offset_;
-
-  // ArtField size in bytes.
-  uint32_t art_fields_size_;
-
-  // Image bitmap offset in the file.
-  uint32_t image_bitmap_offset_;
-
-  // Size of the image bitmap.
-  uint32_t image_bitmap_size_;
-
   // Checksum of the oat file we link to for load time sanity check.
   uint32_t oat_checksum_;
 
@@ -179,12 +200,26 @@
   // Absolute address of an Object[] of objects needed to reinitialize from an image.
   uint32_t image_roots_;
 
+  // Pointer size, this affects the size of the ArtMethods.
+  uint32_t pointer_size_;
+
   // Boolean (0 or 1) to denote if the image was compiled with --compile-pic option
   const uint32_t compile_pic_;
 
+  // Image sections
+  ImageSection sections_[kSectionCount];
+
+  // Image methods.
+  uint64_t image_methods_[kImageMethodsCount];
+
   friend class ImageWriter;
 };
 
+std::ostream& operator<<(std::ostream& os, const ImageHeader::ImageMethod& policy);
+std::ostream& operator<<(std::ostream& os, const ImageHeader::ImageRoot& policy);
+std::ostream& operator<<(std::ostream& os, const ImageHeader::ImageSections& section);
+std::ostream& operator<<(std::ostream& os, const ImageSection& section);
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_IMAGE_H_
diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h
index 39d850f..f70503d 100644
--- a/runtime/indirect_reference_table-inl.h
+++ b/runtime/indirect_reference_table-inl.h
@@ -19,6 +19,7 @@
 
 #include "indirect_reference_table.h"
 
+#include "gc_root-inl.h"
 #include "runtime-inl.h"
 #include "verify_object-inl.h"
 
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 98e6200..4ced23d 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -19,6 +19,7 @@
 #include <sstream>
 
 #include "arch/context.h"
+#include "art_method-inl.h"
 #include "atomic.h"
 #include "class_linker.h"
 #include "debugger.h"
@@ -30,7 +31,6 @@
 #include "interpreter/interpreter.h"
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
 #include "mirror/object_array-inl.h"
@@ -78,15 +78,15 @@
     // could not be initialized or linked with regards to class inheritance.
   } else {
     for (size_t i = 0, e = klass->NumDirectMethods(); i < e; i++) {
-      InstallStubsForMethod(klass->GetDirectMethod(i));
+      InstallStubsForMethod(klass->GetDirectMethod(i, sizeof(void*)));
     }
     for (size_t i = 0, e = klass->NumVirtualMethods(); i < e; i++) {
-      InstallStubsForMethod(klass->GetVirtualMethod(i));
+      InstallStubsForMethod(klass->GetVirtualMethod(i, sizeof(void*)));
     }
   }
 }
 
-static void UpdateEntrypoints(mirror::ArtMethod* method, const void* quick_code)
+static void UpdateEntrypoints(ArtMethod* method, const void* quick_code)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Runtime* const runtime = Runtime::Current();
   jit::Jit* jit = runtime->GetJit();
@@ -114,7 +114,7 @@
   }
 }
 
-void Instrumentation::InstallStubsForMethod(mirror::ArtMethod* method) {
+void Instrumentation::InstallStubsForMethod(ArtMethod* method) {
   if (method->IsAbstract() || method->IsProxyMethod()) {
     // Do not change stubs for these methods.
     return;
@@ -175,7 +175,7 @@
     }
 
     bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-      mirror::ArtMethod* m = GetMethod();
+      ArtMethod* m = GetMethod();
       if (m == nullptr) {
         if (kVerboseInstrumentation) {
           LOG(INFO) << "  Skipping upcall. Frame " << GetFrameId();
@@ -319,7 +319,7 @@
       if (instrumentation_stack_->size() == 0) {
         return false;  // Stop.
       }
-      mirror::ArtMethod* m = GetMethod();
+      ArtMethod* m = GetMethod();
       if (GetCurrentQuickFrame() == nullptr) {
         if (kVerboseInstrumentation) {
           LOG(INFO) << "  Ignoring a shadow frame. Frame " << GetFrameId()
@@ -656,7 +656,7 @@
   }
 }
 
-void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code) {
+void Instrumentation::UpdateMethodsCode(ArtMethod* method, const void* quick_code) {
   DCHECK(method->GetDeclaringClass()->IsResolved());
   const void* new_quick_code;
   if (LIKELY(!instrumentation_stubs_installed_)) {
@@ -679,67 +679,42 @@
   UpdateEntrypoints(method, new_quick_code);
 }
 
-bool Instrumentation::AddDeoptimizedMethod(mirror::ArtMethod* method) {
-  // Note that the insert() below isn't read barrier-aware. So, this
-  // FindDeoptimizedMethod() call is necessary or else we would end up
-  // storing the same method twice in the map (the from-space and the
-  // to-space ones).
-  if (FindDeoptimizedMethod(method)) {
+bool Instrumentation::AddDeoptimizedMethod(ArtMethod* method) {
+  if (IsDeoptimizedMethod(method)) {
     // Already in the map. Return.
     return false;
   }
   // Not found. Add it.
-  static_assert(!kMovingMethods, "Not safe if methods can move");
-  int32_t hash_code = method->IdentityHashCode();
-  deoptimized_methods_.insert(std::make_pair(hash_code, GcRoot<mirror::ArtMethod>(method)));
+  deoptimized_methods_.insert(method);
   return true;
 }
 
-bool Instrumentation::FindDeoptimizedMethod(mirror::ArtMethod* method) {
-  static_assert(!kMovingMethods, "Not safe if methods can move");
-  int32_t hash_code = method->IdentityHashCode();
-  auto range = deoptimized_methods_.equal_range(hash_code);
-  for (auto it = range.first; it != range.second; ++it) {
-    mirror::ArtMethod* m = it->second.Read();
-    if (m == method) {
-      // Found.
-      return true;
-    }
-  }
-  // Not found.
-  return false;
+bool Instrumentation::IsDeoptimizedMethod(ArtMethod* method) {
+  return deoptimized_methods_.find(method) != deoptimized_methods_.end();
 }
 
-mirror::ArtMethod* Instrumentation::BeginDeoptimizedMethod() {
-  auto it = deoptimized_methods_.begin();
-  if (it == deoptimized_methods_.end()) {
+ArtMethod* Instrumentation::BeginDeoptimizedMethod() {
+  if (deoptimized_methods_.empty()) {
     // Empty.
     return nullptr;
   }
-  return it->second.Read();
+  return *deoptimized_methods_.begin();
 }
 
-bool Instrumentation::RemoveDeoptimizedMethod(mirror::ArtMethod* method) {
-  static_assert(!kMovingMethods, "Not safe if methods can move");
-  int32_t hash_code = method->IdentityHashCode();
-  auto range = deoptimized_methods_.equal_range(hash_code);
-  for (auto it = range.first; it != range.second; ++it) {
-    mirror::ArtMethod* m = it->second.Read();
-    if (m == method) {
-      // Found. Erase and return.
-      deoptimized_methods_.erase(it);
-      return true;
-    }
+bool Instrumentation::RemoveDeoptimizedMethod(ArtMethod* method) {
+  auto it = deoptimized_methods_.find(method);
+  if (it == deoptimized_methods_.end()) {
+    return false;
   }
-  // Not found.
-  return false;
+  deoptimized_methods_.erase(it);
+  return true;
 }
 
 bool Instrumentation::IsDeoptimizedMethodsEmpty() const {
   return deoptimized_methods_.empty();
 }
 
-void Instrumentation::Deoptimize(mirror::ArtMethod* method) {
+void Instrumentation::Deoptimize(ArtMethod* method) {
   CHECK(!method->IsNative());
   CHECK(!method->IsProxyMethod());
   CHECK(!method->IsAbstract());
@@ -762,7 +737,7 @@
   }
 }
 
-void Instrumentation::Undeoptimize(mirror::ArtMethod* method) {
+void Instrumentation::Undeoptimize(ArtMethod* method) {
   CHECK(!method->IsNative());
   CHECK(!method->IsProxyMethod());
   CHECK(!method->IsAbstract());
@@ -798,10 +773,10 @@
   }
 }
 
-bool Instrumentation::IsDeoptimized(mirror::ArtMethod* method) {
+bool Instrumentation::IsDeoptimized(ArtMethod* method) {
   DCHECK(method != nullptr);
   ReaderMutexLock mu(Thread::Current(), deoptimized_methods_lock_);
-  return FindDeoptimizedMethod(method);
+  return IsDeoptimizedMethod(method);
 }
 
 void Instrumentation::EnableDeoptimization() {
@@ -819,7 +794,7 @@
   }
   // Undeoptimized selected methods.
   while (true) {
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     {
       ReaderMutexLock mu(Thread::Current(), deoptimized_methods_lock_);
       if (IsDeoptimizedMethodsEmpty()) {
@@ -866,7 +841,7 @@
   ConfigureStubs(key, InstrumentationLevel::kInstrumentNothing);
 }
 
-const void* Instrumentation::GetQuickCodeFor(mirror::ArtMethod* method, size_t pointer_size) const {
+const void* Instrumentation::GetQuickCodeFor(ArtMethod* method, size_t pointer_size) const {
   Runtime* runtime = Runtime::Current();
   if (LIKELY(!instrumentation_stubs_installed_)) {
     const void* code = method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
@@ -883,7 +858,7 @@
 }
 
 void Instrumentation::MethodEnterEventImpl(Thread* thread, mirror::Object* this_object,
-                                           mirror::ArtMethod* method,
+                                           ArtMethod* method,
                                            uint32_t dex_pc) const {
   auto it = method_entry_listeners_.begin();
   bool is_end = (it == method_entry_listeners_.end());
@@ -897,7 +872,7 @@
 }
 
 void Instrumentation::MethodExitEventImpl(Thread* thread, mirror::Object* this_object,
-                                          mirror::ArtMethod* method,
+                                          ArtMethod* method,
                                           uint32_t dex_pc, const JValue& return_value) const {
   auto it = method_exit_listeners_.begin();
   bool is_end = (it == method_exit_listeners_.end());
@@ -911,7 +886,7 @@
 }
 
 void Instrumentation::MethodUnwindEvent(Thread* thread, mirror::Object* this_object,
-                                        mirror::ArtMethod* method,
+                                        ArtMethod* method,
                                         uint32_t dex_pc) const {
   if (HasMethodUnwindListeners()) {
     for (InstrumentationListener* listener : method_unwind_listeners_) {
@@ -921,7 +896,7 @@
 }
 
 void Instrumentation::DexPcMovedEventImpl(Thread* thread, mirror::Object* this_object,
-                                          mirror::ArtMethod* method,
+                                          ArtMethod* method,
                                           uint32_t dex_pc) const {
   std::shared_ptr<std::list<InstrumentationListener*>> original(dex_pc_listeners_);
   for (InstrumentationListener* listener : *original.get()) {
@@ -929,7 +904,7 @@
   }
 }
 
-void Instrumentation::BackwardBranchImpl(Thread* thread, mirror::ArtMethod* method,
+void Instrumentation::BackwardBranchImpl(Thread* thread, ArtMethod* method,
                                          int32_t offset) const {
   for (InstrumentationListener* listener : backward_branch_listeners_) {
     listener->BackwardBranch(thread, method, offset);
@@ -937,7 +912,7 @@
 }
 
 void Instrumentation::FieldReadEventImpl(Thread* thread, mirror::Object* this_object,
-                                         mirror::ArtMethod* method, uint32_t dex_pc,
+                                         ArtMethod* method, uint32_t dex_pc,
                                          ArtField* field) const {
   std::shared_ptr<std::list<InstrumentationListener*>> original(field_read_listeners_);
   for (InstrumentationListener* listener : *original.get()) {
@@ -946,7 +921,7 @@
 }
 
 void Instrumentation::FieldWriteEventImpl(Thread* thread, mirror::Object* this_object,
-                                         mirror::ArtMethod* method, uint32_t dex_pc,
+                                         ArtMethod* method, uint32_t dex_pc,
                                          ArtField* field, const JValue& field_value) const {
   std::shared_ptr<std::list<InstrumentationListener*>> original(field_write_listeners_);
   for (InstrumentationListener* listener : *original.get()) {
@@ -980,7 +955,7 @@
 }
 
 void Instrumentation::PushInstrumentationStackFrame(Thread* self, mirror::Object* this_object,
-                                                    mirror::ArtMethod* method,
+                                                    ArtMethod* method,
                                                     uintptr_t lr, bool interpreter_entry) {
   // We have a callee-save frame meaning this value is guaranteed to never be 0.
   size_t frame_id = StackVisitor::ComputeNumFrames(self, kInstrumentationStackWalk);
@@ -1011,7 +986,7 @@
   CheckStackDepth(self, instrumentation_frame, 0);
   self->VerifyStack();
 
-  mirror::ArtMethod* method = instrumentation_frame.method_;
+  ArtMethod* method = instrumentation_frame.method_;
   uint32_t length;
   char return_shorty = method->GetShorty(&length)[0];
   JValue return_value;
@@ -1064,7 +1039,7 @@
   // TODO: bring back CheckStackDepth(self, instrumentation_frame, 2);
   stack->pop_front();
 
-  mirror::ArtMethod* method = instrumentation_frame.method_;
+  ArtMethod* method = instrumentation_frame.method_;
   if (is_deoptimization) {
     if (kVerboseInstrumentation) {
       LOG(INFO) << "Popping for deoptimization " << PrettyMethod(method);
@@ -1082,17 +1057,6 @@
   }
 }
 
-void Instrumentation::VisitRoots(RootVisitor* visitor) {
-  WriterMutexLock mu(Thread::Current(), deoptimized_methods_lock_);
-  if (IsDeoptimizedMethodsEmpty()) {
-    return;
-  }
-  BufferedRootVisitor<kDefaultBufferedRootCount> roots(visitor, RootInfo(kRootVMInternal));
-  for (auto pair : deoptimized_methods_) {
-    roots.VisitRoot(pair.second);
-  }
-}
-
 std::string InstrumentationStackFrame::Dump() const {
   std::ostringstream os;
   os << "Frame " << frame_id_ << " " << PrettyMethod(method_) << ":"
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 7d70d21..db8e9c2 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -19,7 +19,7 @@
 
 #include <stdint.h>
 #include <list>
-#include <map>
+#include <unordered_set>
 
 #include "arch/instruction_set.h"
 #include "base/macros.h"
@@ -29,12 +29,12 @@
 
 namespace art {
 namespace mirror {
-  class ArtMethod;
   class Class;
   class Object;
   class Throwable;
 }  // namespace mirror
 class ArtField;
+class ArtMethod;
 union JValue;
 class Thread;
 
@@ -62,32 +62,32 @@
 
   // Call-back for when a method is entered.
   virtual void MethodEntered(Thread* thread, mirror::Object* this_object,
-                             mirror::ArtMethod* method,
+                             ArtMethod* method,
                              uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
 
   // Call-back for when a method is exited.
   virtual void MethodExited(Thread* thread, mirror::Object* this_object,
-                            mirror::ArtMethod* method, uint32_t dex_pc,
+                            ArtMethod* method, uint32_t dex_pc,
                             const JValue& return_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
 
   // Call-back for when a method is popped due to an exception throw. A method will either cause a
   // MethodExited call-back or a MethodUnwind call-back when its activation is removed.
   virtual void MethodUnwind(Thread* thread, mirror::Object* this_object,
-                            mirror::ArtMethod* method, uint32_t dex_pc)
+                            ArtMethod* method, uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
 
   // Call-back for when the dex pc moves in a method.
   virtual void DexPcMoved(Thread* thread, mirror::Object* this_object,
-                          mirror::ArtMethod* method, uint32_t new_dex_pc)
+                          ArtMethod* method, uint32_t new_dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
 
   // Call-back for when we read from a field.
-  virtual void FieldRead(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method,
+  virtual void FieldRead(Thread* thread, mirror::Object* this_object, ArtMethod* method,
                          uint32_t dex_pc, ArtField* field) = 0;
 
   // Call-back for when we write into a field.
-  virtual void FieldWritten(Thread* thread, mirror::Object* this_object, mirror::ArtMethod* method,
+  virtual void FieldWritten(Thread* thread, mirror::Object* this_object, ArtMethod* method,
                             uint32_t dex_pc, ArtField* field, const JValue& field_value) = 0;
 
   // Call-back when an exception is caught.
@@ -95,7 +95,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
 
   // Call-back for when we get a backward branch.
-  virtual void BackwardBranch(Thread* thread, mirror::ArtMethod* method, int32_t dex_pc_offset)
+  virtual void BackwardBranch(Thread* thread, ArtMethod* method, int32_t dex_pc_offset)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
 };
 
@@ -162,19 +162,19 @@
   // Deoptimize a method by forcing its execution with the interpreter. Nevertheless, a static
   // method (except a class initializer) set to the resolution trampoline will be deoptimized only
   // once its declaring class is initialized.
-  void Deoptimize(mirror::ArtMethod* method)
+  void Deoptimize(ArtMethod* method)
       LOCKS_EXCLUDED(Locks::thread_list_lock_, deoptimized_methods_lock_)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Undeoptimze the method by restoring its entrypoints. Nevertheless, a static method
   // (except a class initializer) set to the resolution trampoline will be updated only once its
   // declaring class is initialized.
-  void Undeoptimize(mirror::ArtMethod* method)
+  void Undeoptimize(ArtMethod* method)
       LOCKS_EXCLUDED(Locks::thread_list_lock_, deoptimized_methods_lock_)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Indicates whether the method has been deoptimized so it is executed with the interpreter.
-  bool IsDeoptimized(mirror::ArtMethod* method)
+  bool IsDeoptimized(ArtMethod* method)
       LOCKS_EXCLUDED(deoptimized_methods_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -205,13 +205,13 @@
   void ResetQuickAllocEntryPoints() EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_);
 
   // Update the code of a method respecting any installed stubs.
-  void UpdateMethodsCode(mirror::ArtMethod* method, const void* quick_code)
+  void UpdateMethodsCode(ArtMethod* method, const void* quick_code)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get the quick code for the given method. More efficient than asking the class linker as it
   // will short-cut to GetCode if instrumentation and static method resolution stubs aren't
   // installed.
-  const void* GetQuickCodeFor(mirror::ArtMethod* method, size_t pointer_size) const
+  const void* GetQuickCodeFor(ArtMethod* method, size_t pointer_size) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void ForceInterpretOnly() {
@@ -273,7 +273,7 @@
   // Inform listeners that a method has been entered. A dex PC is provided as we may install
   // listeners into executing code and get method enter events for methods already on the stack.
   void MethodEnterEvent(Thread* thread, mirror::Object* this_object,
-                        mirror::ArtMethod* method, uint32_t dex_pc) const
+                        ArtMethod* method, uint32_t dex_pc) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (UNLIKELY(HasMethodEntryListeners())) {
       MethodEnterEventImpl(thread, this_object, method, dex_pc);
@@ -282,7 +282,7 @@
 
   // Inform listeners that a method has been exited.
   void MethodExitEvent(Thread* thread, mirror::Object* this_object,
-                       mirror::ArtMethod* method, uint32_t dex_pc,
+                       ArtMethod* method, uint32_t dex_pc,
                        const JValue& return_value) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (UNLIKELY(HasMethodExitListeners())) {
@@ -292,12 +292,12 @@
 
   // Inform listeners that a method has been exited due to an exception.
   void MethodUnwindEvent(Thread* thread, mirror::Object* this_object,
-                         mirror::ArtMethod* method, uint32_t dex_pc) const
+                         ArtMethod* method, uint32_t dex_pc) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Inform listeners that the dex pc has moved (only supported by the interpreter).
   void DexPcMovedEvent(Thread* thread, mirror::Object* this_object,
-                       mirror::ArtMethod* method, uint32_t dex_pc) const
+                       ArtMethod* method, uint32_t dex_pc) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (UNLIKELY(HasDexPcListeners())) {
       DexPcMovedEventImpl(thread, this_object, method, dex_pc);
@@ -305,7 +305,7 @@
   }
 
   // Inform listeners that a backward branch has been taken (only supported by the interpreter).
-  void BackwardBranch(Thread* thread, mirror::ArtMethod* method, int32_t offset) const
+  void BackwardBranch(Thread* thread, ArtMethod* method, int32_t offset) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (UNLIKELY(HasBackwardBranchListeners())) {
       BackwardBranchImpl(thread, method, offset);
@@ -314,7 +314,7 @@
 
   // Inform listeners that we read a field (only supported by the interpreter).
   void FieldReadEvent(Thread* thread, mirror::Object* this_object,
-                      mirror::ArtMethod* method, uint32_t dex_pc,
+                      ArtMethod* method, uint32_t dex_pc,
                       ArtField* field) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (UNLIKELY(HasFieldReadListeners())) {
@@ -324,7 +324,7 @@
 
   // Inform listeners that we write a field (only supported by the interpreter).
   void FieldWriteEvent(Thread* thread, mirror::Object* this_object,
-                       mirror::ArtMethod* method, uint32_t dex_pc,
+                       ArtMethod* method, uint32_t dex_pc,
                        ArtField* field, const JValue& field_value) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (UNLIKELY(HasFieldWriteListeners())) {
@@ -339,7 +339,7 @@
   // Called when an instrumented method is entered. The intended link register (lr) is saved so
   // that returning causes a branch to the method exit stub. Generates method enter events.
   void PushInstrumentationStackFrame(Thread* self, mirror::Object* this_object,
-                                     mirror::ArtMethod* method, uintptr_t lr,
+                                     ArtMethod* method, uintptr_t lr,
                                      bool interpreter_entry)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -356,12 +356,9 @@
   // Call back for configure stubs.
   void InstallStubsForClass(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void InstallStubsForMethod(mirror::ArtMethod* method)
+  void InstallStubsForMethod(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      LOCKS_EXCLUDED(deoptimized_methods_lock_);
-
  private:
   InstrumentationLevel GetCurrentInstrumentationLevel() const;
 
@@ -384,42 +381,39 @@
   void SetEntrypointsInstrumented(bool instrumented) NO_THREAD_SAFETY_ANALYSIS;
 
   void MethodEnterEventImpl(Thread* thread, mirror::Object* this_object,
-                            mirror::ArtMethod* method, uint32_t dex_pc) const
+                            ArtMethod* method, uint32_t dex_pc) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void MethodExitEventImpl(Thread* thread, mirror::Object* this_object,
-                           mirror::ArtMethod* method,
+                           ArtMethod* method,
                            uint32_t dex_pc, const JValue& return_value) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void DexPcMovedEventImpl(Thread* thread, mirror::Object* this_object,
-                           mirror::ArtMethod* method, uint32_t dex_pc) const
+                           ArtMethod* method, uint32_t dex_pc) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void BackwardBranchImpl(Thread* thread, mirror::ArtMethod* method, int32_t offset) const
+  void BackwardBranchImpl(Thread* thread, ArtMethod* method, int32_t offset) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FieldReadEventImpl(Thread* thread, mirror::Object* this_object,
-                           mirror::ArtMethod* method, uint32_t dex_pc,
+                           ArtMethod* method, uint32_t dex_pc,
                            ArtField* field) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void FieldWriteEventImpl(Thread* thread, mirror::Object* this_object,
-                           mirror::ArtMethod* method, uint32_t dex_pc,
+                           ArtMethod* method, uint32_t dex_pc,
                            ArtField* field, const JValue& field_value) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Read barrier-aware utility functions for accessing deoptimized_methods_
-  bool AddDeoptimizedMethod(mirror::ArtMethod* method)
+  bool AddDeoptimizedMethod(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       EXCLUSIVE_LOCKS_REQUIRED(deoptimized_methods_lock_);
-  bool FindDeoptimizedMethod(mirror::ArtMethod* method)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      SHARED_LOCKS_REQUIRED(deoptimized_methods_lock_);
-  bool RemoveDeoptimizedMethod(mirror::ArtMethod* method)
+  bool IsDeoptimizedMethod(ArtMethod* method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, deoptimized_methods_lock_);
+  bool RemoveDeoptimizedMethod(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       EXCLUSIVE_LOCKS_REQUIRED(deoptimized_methods_lock_);
-  mirror::ArtMethod* BeginDeoptimizedMethod()
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      SHARED_LOCKS_REQUIRED(deoptimized_methods_lock_);
+  ArtMethod* BeginDeoptimizedMethod()
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, deoptimized_methods_lock_);
   bool IsDeoptimizedMethodsEmpty() const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      SHARED_LOCKS_REQUIRED(deoptimized_methods_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, deoptimized_methods_lock_);
 
   // Have we hijacked ArtMethod::code_ so that it calls instrumentation/interpreter code?
   bool instrumentation_stubs_installed_;
@@ -488,8 +482,7 @@
   // The set of methods being deoptimized (by the debugger) which must be executed with interpreter
   // only.
   mutable ReaderWriterMutex deoptimized_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
-  std::multimap<int32_t, GcRoot<mirror::ArtMethod>> deoptimized_methods_
-      GUARDED_BY(deoptimized_methods_lock_);
+  std::unordered_set<ArtMethod*> deoptimized_methods_ GUARDED_BY(deoptimized_methods_lock_);
   bool deoptimization_enabled_;
 
   // Current interpreter handler table. This is updated each time the thread state flags are
@@ -509,7 +502,7 @@
 
 // An element in the instrumentation side stack maintained in art::Thread.
 struct InstrumentationStackFrame {
-  InstrumentationStackFrame(mirror::Object* this_object, mirror::ArtMethod* method,
+  InstrumentationStackFrame(mirror::Object* this_object, ArtMethod* method,
                             uintptr_t return_pc, size_t frame_id, bool interpreter_entry)
       : this_object_(this_object), method_(method), return_pc_(return_pc), frame_id_(frame_id),
         interpreter_entry_(interpreter_entry) {
@@ -518,7 +511,7 @@
   std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::Object* this_object_;
-  mirror::ArtMethod* method_;
+  ArtMethod* method_;
   uintptr_t return_pc_;
   size_t frame_id_;
   bool interpreter_entry_;
diff --git a/runtime/instrumentation_test.cc b/runtime/instrumentation_test.cc
index 5afacb8..85bb8c4 100644
--- a/runtime/instrumentation_test.cc
+++ b/runtime/instrumentation_test.cc
@@ -42,7 +42,7 @@
 
   void MethodEntered(Thread* thread ATTRIBUTE_UNUSED,
                      mirror::Object* this_object ATTRIBUTE_UNUSED,
-                     mirror::ArtMethod* method ATTRIBUTE_UNUSED,
+                     ArtMethod* method ATTRIBUTE_UNUSED,
                      uint32_t dex_pc ATTRIBUTE_UNUSED)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     received_method_enter_event = true;
@@ -50,7 +50,7 @@
 
   void MethodExited(Thread* thread ATTRIBUTE_UNUSED,
                     mirror::Object* this_object ATTRIBUTE_UNUSED,
-                    mirror::ArtMethod* method ATTRIBUTE_UNUSED,
+                    ArtMethod* method ATTRIBUTE_UNUSED,
                     uint32_t dex_pc ATTRIBUTE_UNUSED,
                     const JValue& return_value ATTRIBUTE_UNUSED)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -59,7 +59,7 @@
 
   void MethodUnwind(Thread* thread ATTRIBUTE_UNUSED,
                     mirror::Object* this_object ATTRIBUTE_UNUSED,
-                    mirror::ArtMethod* method ATTRIBUTE_UNUSED,
+                    ArtMethod* method ATTRIBUTE_UNUSED,
                     uint32_t dex_pc ATTRIBUTE_UNUSED)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     received_method_unwind_event = true;
@@ -67,7 +67,7 @@
 
   void DexPcMoved(Thread* thread ATTRIBUTE_UNUSED,
                   mirror::Object* this_object ATTRIBUTE_UNUSED,
-                  mirror::ArtMethod* method ATTRIBUTE_UNUSED,
+                  ArtMethod* method ATTRIBUTE_UNUSED,
                   uint32_t new_dex_pc ATTRIBUTE_UNUSED)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     received_dex_pc_moved_event = true;
@@ -75,7 +75,7 @@
 
   void FieldRead(Thread* thread ATTRIBUTE_UNUSED,
                  mirror::Object* this_object ATTRIBUTE_UNUSED,
-                 mirror::ArtMethod* method ATTRIBUTE_UNUSED,
+                 ArtMethod* method ATTRIBUTE_UNUSED,
                  uint32_t dex_pc ATTRIBUTE_UNUSED,
                  ArtField* field ATTRIBUTE_UNUSED)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -84,7 +84,7 @@
 
   void FieldWritten(Thread* thread ATTRIBUTE_UNUSED,
                     mirror::Object* this_object ATTRIBUTE_UNUSED,
-                    mirror::ArtMethod* method ATTRIBUTE_UNUSED,
+                    ArtMethod* method ATTRIBUTE_UNUSED,
                     uint32_t dex_pc ATTRIBUTE_UNUSED,
                     ArtField* field ATTRIBUTE_UNUSED,
                     const JValue& field_value ATTRIBUTE_UNUSED)
@@ -99,7 +99,7 @@
   }
 
   void BackwardBranch(Thread* thread ATTRIBUTE_UNUSED,
-                      mirror::ArtMethod* method ATTRIBUTE_UNUSED,
+                      ArtMethod* method ATTRIBUTE_UNUSED,
                       int32_t dex_pc_offset ATTRIBUTE_UNUSED)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     received_backward_branch_event = true;
@@ -170,7 +170,7 @@
       soa.Self()->TransitionFromSuspendedToRunnable();
     }
 
-    mirror::ArtMethod* const event_method = nullptr;
+    ArtMethod* const event_method = nullptr;
     mirror::Object* const event_obj = nullptr;
     const uint32_t event_dex_pc = 0;
 
@@ -197,8 +197,7 @@
     EXPECT_FALSE(DidListenerReceiveEvent(listener, instrumentation_event));
   }
 
-  void DeoptimizeMethod(Thread* self, Handle<mirror::ArtMethod> method,
-                        bool enable_deoptimization)
+  void DeoptimizeMethod(Thread* self, ArtMethod* method, bool enable_deoptimization)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Runtime* runtime = Runtime::Current();
     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
@@ -207,19 +206,19 @@
     if (enable_deoptimization) {
       instrumentation->EnableDeoptimization();
     }
-    instrumentation->Deoptimize(method.Get());
+    instrumentation->Deoptimize(method);
     runtime->GetThreadList()->ResumeAll();
     self->TransitionFromSuspendedToRunnable();
   }
 
-  void UndeoptimizeMethod(Thread* self, Handle<mirror::ArtMethod> method,
+  void UndeoptimizeMethod(Thread* self, ArtMethod* method,
                           const char* key, bool disable_deoptimization)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Runtime* runtime = Runtime::Current();
     instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
     self->TransitionFromRunnableToSuspended(kSuspended);
     runtime->GetThreadList()->SuspendAll("Single method undeoptimization");
-    instrumentation->Undeoptimize(method.Get());
+    instrumentation->Undeoptimize(method);
     if (disable_deoptimization) {
       instrumentation->DisableDeoptimization(key);
     }
@@ -304,7 +303,7 @@
   }
 
   static void ReportEvent(const instrumentation::Instrumentation* instr, uint32_t event_type,
-                          Thread* self, mirror::ArtMethod* method, mirror::Object* obj,
+                          Thread* self, ArtMethod* method, mirror::Object* obj,
                           uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     switch (event_type) {
@@ -434,28 +433,28 @@
   Runtime* const runtime = Runtime::Current();
   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
   ClassLinker* class_linker = runtime->GetClassLinker();
-  StackHandleScope<2> hs(soa.Self());
+  StackHandleScope<1> hs(soa.Self());
   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
   mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
   ASSERT_TRUE(klass != nullptr);
-  Handle<mirror::ArtMethod> method_to_deoptimize(
-      hs.NewHandle(klass->FindDeclaredDirectMethod("instanceMethod", "()V")));
-  ASSERT_TRUE(method_to_deoptimize.Get() != nullptr);
+  ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
+                                                                    sizeof(void*));
+  ASSERT_TRUE(method_to_deoptimize != nullptr);
 
   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
-  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize.Get()));
+  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
 
   DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
 
   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
   EXPECT_TRUE(instr->AreExitStubsInstalled());
-  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize.Get()));
+  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
 
   constexpr const char* instrumentation_key = "DeoptimizeDirectMethod";
   UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
 
   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
-  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize.Get()));
+  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
 }
 
 TEST_F(InstrumentationTest, FullDeoptimization) {
@@ -481,16 +480,16 @@
   Runtime* const runtime = Runtime::Current();
   instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
   ClassLinker* class_linker = runtime->GetClassLinker();
-  StackHandleScope<2> hs(soa.Self());
+  StackHandleScope<1> hs(soa.Self());
   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(class_loader)));
   mirror::Class* klass = class_linker->FindClass(soa.Self(), "LInstrumentation;", loader);
   ASSERT_TRUE(klass != nullptr);
-  Handle<mirror::ArtMethod> method_to_deoptimize(
-      hs.NewHandle(klass->FindDeclaredDirectMethod("instanceMethod", "()V")));
-  ASSERT_TRUE(method_to_deoptimize.Get() != nullptr);
+  ArtMethod* method_to_deoptimize = klass->FindDeclaredDirectMethod("instanceMethod", "()V",
+                                                                    sizeof(void*));
+  ASSERT_TRUE(method_to_deoptimize != nullptr);
 
   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
-  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize.Get()));
+  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
 
   DeoptimizeMethod(soa.Self(), method_to_deoptimize, true);
   // Deoptimizing a method does not change instrumentation level.
@@ -498,7 +497,7 @@
             GetCurrentInstrumentationLevel());
   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
   EXPECT_TRUE(instr->AreExitStubsInstalled());
-  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize.Get()));
+  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
 
   constexpr const char* instrumentation_key = "MixedDeoptimization";
   DeoptimizeEverything(soa.Self(), instrumentation_key, false);
@@ -506,20 +505,20 @@
             GetCurrentInstrumentationLevel());
   EXPECT_TRUE(instr->AreAllMethodsDeoptimized());
   EXPECT_TRUE(instr->AreExitStubsInstalled());
-  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize.Get()));
+  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
 
   UndeoptimizeEverything(soa.Self(), instrumentation_key, false);
   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
             GetCurrentInstrumentationLevel());
   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
   EXPECT_TRUE(instr->AreExitStubsInstalled());
-  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize.Get()));
+  EXPECT_TRUE(instr->IsDeoptimized(method_to_deoptimize));
 
   UndeoptimizeMethod(soa.Self(), method_to_deoptimize, instrumentation_key, true);
   EXPECT_EQ(Instrumentation::InstrumentationLevel::kInstrumentNothing,
             GetCurrentInstrumentationLevel());
   EXPECT_FALSE(instr->AreAllMethodsDeoptimized());
-  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize.Get()));
+  EXPECT_FALSE(instr->IsDeoptimized(method_to_deoptimize));
 }
 
 TEST_F(InstrumentationTest, MethodTracing_Interpreter) {
diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc
index a85d10f..9abbca8 100644
--- a/runtime/intern_table.cc
+++ b/runtime/intern_table.cc
@@ -18,6 +18,7 @@
 
 #include <memory>
 
+#include "gc_root-inl.h"
 #include "gc/space/image_space.h"
 #include "mirror/dex_cache.h"
 #include "mirror/object_array-inl.h"
diff --git a/runtime/interpreter/interpreter.h b/runtime/interpreter/interpreter.h
index 7d634b3..446c5bb4 100644
--- a/runtime/interpreter/interpreter.h
+++ b/runtime/interpreter/interpreter.h
@@ -22,10 +22,10 @@
 
 namespace art {
 namespace mirror {
-class ArtMethod;
 class Object;
 }  // namespace mirror
 
+class ArtMethod;
 union JValue;
 class ShadowFrame;
 class Thread;
@@ -33,7 +33,7 @@
 namespace interpreter {
 
 // Called by ArtMethod::Invoke, shadow frames arguments are taken from the args array.
-extern void EnterInterpreterFromInvoke(Thread* self, mirror::ArtMethod* method,
+extern void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method,
                                        mirror::Object* receiver, uint32_t* args, JValue* result)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 363c65a..1ed1a64 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -413,25 +413,19 @@
 #undef EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL
 #undef EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL
 
-uint32_t FindNextInstructionFollowingException(Thread* self,
-                                               ShadowFrame& shadow_frame,
-                                               uint32_t dex_pc,
-                                               const instrumentation::Instrumentation* instrumentation) {
+uint32_t FindNextInstructionFollowingException(
+    Thread* self, ShadowFrame& shadow_frame, uint32_t dex_pc,
+    const instrumentation::Instrumentation* instrumentation) {
   self->VerifyStack();
-  StackHandleScope<3> hs(self);
+  StackHandleScope<2> hs(self);
   Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException()));
   if (instrumentation->HasExceptionCaughtListeners()
       && self->IsExceptionThrownByCurrentMethod(exception.Get())) {
     instrumentation->ExceptionCaughtEvent(self, exception.Get());
   }
   bool clear_exception = false;
-  uint32_t found_dex_pc;
-  {
-    Handle<mirror::Class> exception_class(hs.NewHandle(exception->GetClass()));
-    Handle<mirror::ArtMethod> h_method(hs.NewHandle(shadow_frame.GetMethod()));
-    found_dex_pc = mirror::ArtMethod::FindCatchBlock(h_method, exception_class, dex_pc,
-                                                     &clear_exception);
-  }
+  uint32_t found_dex_pc = shadow_frame.GetMethod()->FindCatchBlock(
+      hs.NewHandle(exception->GetClass()), dex_pc, &clear_exception);
   if (found_dex_pc == DexFile::kDexNoIndex) {
     // Exception is not caught by the current method. We will unwind to the
     // caller. Notify any instrumentation listener.
@@ -651,7 +645,7 @@
       UNREACHABLE();
     }
     // Force the use of interpreter when it is required by the debugger.
-    mirror::EntryPointFromInterpreter* entry;
+    EntryPointFromInterpreter* entry;
     if (UNLIKELY(Dbg::IsForcedInterpreterNeededForCalling(self, new_shadow_frame->GetMethod()))) {
       entry = &art::artInterpreterToInterpreterBridge;
     } else {
@@ -668,7 +662,7 @@
     shadow_frame.SetVRegReference(vregC, result->GetL());
     // Overwrite all potential copies of the original result of the new-instance of string with the
     // new result of the StringFactory. Use the verifier to find this set of registers.
-    mirror::ArtMethod* method = shadow_frame.GetMethod();
+    ArtMethod* method = shadow_frame.GetMethod();
     MethodReference method_ref = method->ToMethodReference();
     SafeMap<uint32_t, std::set<uint32_t>> string_init_map;
     SafeMap<uint32_t, std::set<uint32_t>>* string_init_map_ptr;
@@ -788,13 +782,17 @@
       RecordArrayElementsInTransactionImpl(array->AsShortArray(), count);
       break;
     case Primitive::kPrimInt:
-    case Primitive::kPrimFloat:
       RecordArrayElementsInTransactionImpl(array->AsIntArray(), count);
       break;
+    case Primitive::kPrimFloat:
+      RecordArrayElementsInTransactionImpl(array->AsFloatArray(), count);
+      break;
     case Primitive::kPrimLong:
-    case Primitive::kPrimDouble:
       RecordArrayElementsInTransactionImpl(array->AsLongArray(), count);
       break;
+    case Primitive::kPrimDouble:
+      RecordArrayElementsInTransactionImpl(array->AsDoubleArray(), count);
+      break;
     default:
       LOG(FATAL) << "Unsupported primitive type " << primitive_component_type
                  << " in fill-array-data";
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 6acc72e..6fafcd1 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -25,6 +25,7 @@
 #include <sstream>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "class_linker-inl.h"
@@ -33,7 +34,6 @@
 #include "dex_instruction-inl.h"
 #include "entrypoints/entrypoint_utils-inl.h"
 #include "handle_scope-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
@@ -41,7 +41,7 @@
 #include "thread.h"
 #include "well_known_classes.h"
 
-using ::art::mirror::ArtMethod;
+using ::art::ArtMethod;
 using ::art::mirror::Array;
 using ::art::mirror::BooleanArray;
 using ::art::mirror::ByteArray;
@@ -105,7 +105,7 @@
   const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
   const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
   Object* receiver = (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC);
-  mirror::ArtMethod* sf_method = shadow_frame.GetMethod();
+  ArtMethod* sf_method = shadow_frame.GetMethod();
   ArtMethod* const called_method = FindMethodFromCode<type, do_access_check>(
       method_idx, &receiver, &sf_method, self);
   // The shadow frame should already be pushed, so we don't need to update it.
@@ -139,7 +139,8 @@
   }
   const uint32_t vtable_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
   CHECK(receiver->GetClass()->ShouldHaveEmbeddedImtAndVTable());
-  ArtMethod* const called_method = receiver->GetClass()->GetEmbeddedVTableEntry(vtable_idx);
+  ArtMethod* const called_method = receiver->GetClass()->GetEmbeddedVTableEntry(
+      vtable_idx, sizeof(void*));
   if (UNLIKELY(called_method == nullptr)) {
     CHECK(self->IsExceptionPending());
     result->SetJ(0);
@@ -184,7 +185,6 @@
 // java.lang.String class is initialized.
 static inline String* ResolveString(Thread* self, ShadowFrame& shadow_frame, uint32_t string_idx)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  CHECK(!kMovingMethods);
   Class* java_lang_string_class = String::GetJavaLangString();
   if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -195,7 +195,7 @@
       return nullptr;
     }
   }
-  mirror::ArtMethod* method = shadow_frame.GetMethod();
+  ArtMethod* method = shadow_frame.GetMethod();
   mirror::Class* declaring_class = method->GetDeclaringClass();
   mirror::String* s = declaring_class->GetDexCacheStrings()->Get(string_idx);
   if (UNLIKELY(s == nullptr)) {
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index dd1f55e..86027c5 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -1042,7 +1042,8 @@
       HANDLE_PENDING_EXCEPTION();
     } else {
       int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      IntArray* array = a->AsIntArray();
+      DCHECK(a->IsIntArray() || a->IsFloatArray()) << PrettyTypeOf(a);
+      auto* array = down_cast<IntArray*>(a);
       if (LIKELY(array->CheckIsValidIndex(index))) {
         shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
         ADVANCE(2);
@@ -1060,7 +1061,8 @@
       HANDLE_PENDING_EXCEPTION();
     } else {
       int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      LongArray* array = a->AsLongArray();
+      DCHECK(a->IsLongArray() || a->IsDoubleArray()) << PrettyTypeOf(a);
+      auto* array = down_cast<LongArray*>(a);
       if (LIKELY(array->CheckIsValidIndex(index))) {
         shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
         ADVANCE(2);
@@ -1173,7 +1175,8 @@
     } else {
       int32_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
       int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      IntArray* array = a->AsIntArray();
+      DCHECK(a->IsIntArray() || a->IsFloatArray()) << PrettyTypeOf(a);
+      auto* array = down_cast<IntArray*>(a);
       if (LIKELY(array->CheckIsValidIndex(index))) {
         array->SetWithoutChecks<transaction_active>(index, val);
         ADVANCE(2);
@@ -1192,7 +1195,8 @@
     } else {
       int64_t val = shadow_frame.GetVRegLong(inst->VRegA_23x(inst_data));
       int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      LongArray* array = a->AsLongArray();
+      DCHECK(a->IsLongArray() || a->IsDoubleArray()) << PrettyTypeOf(a);
+      auto* array = down_cast<LongArray*>(a);
       if (LIKELY(array->CheckIsValidIndex(index))) {
         array->SetWithoutChecks<transaction_active>(index, val);
         ADVANCE(2);
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 0e3420f..dd7aa40 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -888,7 +888,8 @@
           break;
         }
         int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-        IntArray* array = a->AsIntArray();
+        DCHECK(a->IsIntArray() || a->IsFloatArray()) << PrettyTypeOf(a);
+        auto* array = down_cast<IntArray*>(a);
         if (array->CheckIsValidIndex(index)) {
           shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
           inst = inst->Next_2xx();
@@ -906,7 +907,8 @@
           break;
         }
         int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-        LongArray* array = a->AsLongArray();
+        DCHECK(a->IsLongArray() || a->IsDoubleArray()) << PrettyTypeOf(a);
+        auto* array = down_cast<LongArray*>(a);
         if (array->CheckIsValidIndex(index)) {
           shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
           inst = inst->Next_2xx();
@@ -1019,7 +1021,8 @@
         }
         int32_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
         int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-        IntArray* array = a->AsIntArray();
+        DCHECK(a->IsIntArray() || a->IsFloatArray()) << PrettyTypeOf(a);
+        auto* array = down_cast<IntArray*>(a);
         if (array->CheckIsValidIndex(index)) {
           array->SetWithoutChecks<transaction_active>(index, val);
           inst = inst->Next_2xx();
@@ -1038,7 +1041,8 @@
         }
         int64_t val = shadow_frame.GetVRegLong(inst->VRegA_23x(inst_data));
         int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-        LongArray* array = a->AsLongArray();
+        DCHECK(a->IsLongArray() || a->IsDoubleArray()) << PrettyTypeOf(a);
+        LongArray* array = down_cast<LongArray*>(a);
         if (array->CheckIsValidIndex(index)) {
           array->SetWithoutChecks<transaction_active>(index, val);
           inst = inst->Next_2xx();
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 738e52b..43e24fa 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -21,6 +21,7 @@
 
 #include "ScopedLocalRef.h"
 
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "class_linker.h"
@@ -29,7 +30,6 @@
 #include "handle_scope-inl.h"
 #include "interpreter/interpreter_common.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class.h"
 #include "mirror/field-inl.h"
 #include "mirror/object-inl.h"
@@ -121,8 +121,7 @@
 }
 
 void UnstartedRuntime::UnstartedClassForName(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
   if (class_name == nullptr) {
     return;
@@ -135,8 +134,7 @@
 }
 
 void UnstartedRuntime::UnstartedClassForNameLong(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
   if (class_name == nullptr) {
     return;
@@ -153,8 +151,7 @@
 }
 
 void UnstartedRuntime::UnstartedClassClassForName(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
   if (class_name == nullptr) {
     return;
@@ -171,9 +168,8 @@
 }
 
 void UnstartedRuntime::UnstartedClassNewInstance(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  StackHandleScope<3> hs(self);  // Class, constructor, object.
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
+  StackHandleScope<2> hs(self);  // Class, constructor, object.
   mirror::Object* param = shadow_frame->GetVRegReference(arg_offset);
   if (param == nullptr) {
     AbortTransactionOrFail(self, "Null-pointer in Class.newInstance.");
@@ -202,13 +198,13 @@
   //  2) If we can't find the default constructor. We'll postpone the exception to runtime.
   // Note that 2) could likely be handled here, but for safety abort the transaction.
   bool ok = false;
-  if (Runtime::Current()->GetClassLinker()->EnsureInitialized(self, h_klass, true, true)) {
-    Handle<mirror::ArtMethod> h_cons(hs.NewHandle(
-        h_klass->FindDeclaredDirectMethod("<init>", "()V")));
-    if (h_cons.Get() != nullptr) {
+  auto* cl = Runtime::Current()->GetClassLinker();
+  if (cl->EnsureInitialized(self, h_klass, true, true)) {
+    auto* cons = h_klass->FindDeclaredDirectMethod("<init>", "()V", cl->GetImagePointerSize());
+    if (cons != nullptr) {
       Handle<mirror::Object> h_obj(hs.NewHandle(klass->AllocObject(self)));
       CHECK(h_obj.Get() != nullptr);  // We don't expect OOM at compile-time.
-      EnterInterpreterFromInvoke(self, h_cons.Get(), h_obj.Get(), nullptr, nullptr);
+      EnterInterpreterFromInvoke(self, cons, h_obj.Get(), nullptr, nullptr);
       if (!self->IsExceptionPending()) {
         result->SetL(h_obj.Get());
         ok = true;
@@ -227,8 +223,7 @@
 }
 
 void UnstartedRuntime::UnstartedClassGetDeclaredField(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
   // going the reflective Dex way.
   mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
@@ -266,8 +261,7 @@
 }
 
 void UnstartedRuntime::UnstartedVmClassLoaderFindLoadedClass(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
   mirror::ClassLoader* class_loader =
       down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset));
@@ -286,11 +280,9 @@
   }
 }
 
-void UnstartedRuntime::UnstartedVoidLookupType(Thread* self ATTRIBUTE_UNUSED,
-                                    ShadowFrame* shadow_frame ATTRIBUTE_UNUSED,
-                                    JValue* result,
-                                    size_t arg_offset ATTRIBUTE_UNUSED)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedVoidLookupType(
+    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame ATTRIBUTE_UNUSED, JValue* result,
+    size_t arg_offset ATTRIBUTE_UNUSED) {
   result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V'));
 }
 
@@ -324,8 +316,7 @@
 }
 
 void UnstartedRuntime::UnstartedSystemArraycopy(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
   // Special case array copying without initializing System.
   jint src_pos = shadow_frame->GetVReg(arg_offset + 1);
   jint dst_pos = shadow_frame->GetVReg(arg_offset + 3);
@@ -410,22 +401,19 @@
 }
 
 void UnstartedRuntime::UnstartedSystemArraycopyChar(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   // Just forward.
   UnstartedRuntime::UnstartedSystemArraycopy(self, shadow_frame, result, arg_offset);
 }
 
 void UnstartedRuntime::UnstartedSystemArraycopyInt(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   // Just forward.
   UnstartedRuntime::UnstartedSystemArraycopy(self, shadow_frame, result, arg_offset);
 }
 
 void UnstartedRuntime::UnstartedThreadLocalGet(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset ATTRIBUTE_UNUSED) {
   std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod()));
   bool ok = false;
   if (caller == "java.lang.String java.lang.IntegralToString.convertInt"
@@ -450,8 +438,9 @@
         Handle<mirror::Object> h_real_to_string_obj(hs.NewHandle(
             h_real_to_string_class->AllocObject(self)));
         if (h_real_to_string_obj.Get() != nullptr) {
-          mirror::ArtMethod* init_method =
-              h_real_to_string_class->FindDirectMethod("<init>", "()V");
+          auto* cl = Runtime::Current()->GetClassLinker();
+          ArtMethod* init_method = h_real_to_string_class->FindDirectMethod(
+              "<init>", "()V", cl->GetImagePointerSize());
           if (init_method == nullptr) {
             h_real_to_string_class->DumpClass(LOG(FATAL), mirror::Class::kDumpClassFullDetail);
           } else {
@@ -488,16 +477,8 @@
   result->SetD(out);
 }
 
-void UnstartedRuntime::UnstartedArtMethodGetMethodName(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ArtMethod* method = shadow_frame->GetVRegReference(arg_offset)->AsArtMethod();
-  result->SetL(method->GetNameAsString(self));
-}
-
 void UnstartedRuntime::UnstartedObjectHashCode(
-    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   mirror::Object* obj = shadow_frame->GetVRegReference(arg_offset);
   result->SetI(obj->IdentityHashCode());
 }
@@ -537,8 +518,7 @@
 }
 
 void UnstartedRuntime::UnstartedDexCacheGetDexNative(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   // We will create the Dex object, but the image writer will release it before creating the
   // art file.
   mirror::Object* src = shadow_frame->GetVRegReference(arg_offset);
@@ -600,26 +580,22 @@
 }
 
 void UnstartedRuntime::UnstartedMemoryPeekByte(
-    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   UnstartedMemoryPeek(Primitive::kPrimByte, shadow_frame, result, arg_offset);
 }
 
 void UnstartedRuntime::UnstartedMemoryPeekShort(
-    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   UnstartedMemoryPeek(Primitive::kPrimShort, shadow_frame, result, arg_offset);
 }
 
 void UnstartedRuntime::UnstartedMemoryPeekInt(
-    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   UnstartedMemoryPeek(Primitive::kPrimInt, shadow_frame, result, arg_offset);
 }
 
 void UnstartedRuntime::UnstartedMemoryPeekLong(
-    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self ATTRIBUTE_UNUSED, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   UnstartedMemoryPeek(Primitive::kPrimLong, shadow_frame, result, arg_offset);
 }
 
@@ -673,18 +649,14 @@
 }
 
 void UnstartedRuntime::UnstartedMemoryPeekByteArray(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
   UnstartedMemoryPeekArray(Primitive::kPrimByte, self, shadow_frame, arg_offset);
 }
 
 // This allows reading security.properties in an unstarted runtime and initialize Security.
 void UnstartedRuntime::UnstartedSecurityGetSecurityPropertiesReader(
-    Thread* self,
-    ShadowFrame* shadow_frame ATTRIBUTE_UNUSED,
-    JValue* result,
-    size_t arg_offset ATTRIBUTE_UNUSED)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame ATTRIBUTE_UNUSED, JValue* result,
+    size_t arg_offset ATTRIBUTE_UNUSED) {
   Runtime* runtime = Runtime::Current();
   const std::vector<const DexFile*>& path = runtime->GetClassLinker()->GetBootClassPath();
   std::string canonical(DexFile::GetDexCanonicalLocation(path[0]->GetLocation().c_str()));
@@ -753,8 +725,9 @@
     return;
   }
 
-  mirror::ArtMethod* constructor = h_class->FindDeclaredDirectMethod("<init>",
-                                                                     "(Ljava/lang/String;)V");
+  auto* cl = Runtime::Current()->GetClassLinker();
+  ArtMethod* constructor = h_class->FindDeclaredDirectMethod(
+      "<init>", "(Ljava/lang/String;)V", cl->GetImagePointerSize());
   if (constructor == nullptr) {
     AbortTransactionOrFail(self, "Could not find StringReader constructor");
     return;
@@ -774,8 +747,7 @@
 
 // This allows reading the new style of String objects during compilation.
 void UnstartedRuntime::UnstartedStringGetCharsNoCheck(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
   jint start = shadow_frame->GetVReg(arg_offset + 1);
   jint end = shadow_frame->GetVReg(arg_offset + 2);
   jint index = shadow_frame->GetVReg(arg_offset + 4);
@@ -787,7 +759,8 @@
   DCHECK_GE(start, 0);
   DCHECK_GE(end, string->GetLength());
   StackHandleScope<1> hs(self);
-  Handle<mirror::CharArray> h_char_array(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 3)->AsCharArray()));
+  Handle<mirror::CharArray> h_char_array(
+      hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 3)->AsCharArray()));
   DCHECK_LE(index, h_char_array->GetLength());
   DCHECK_LE(end - start, h_char_array->GetLength() - index);
   string->GetChars(start, end, h_char_array, index);
@@ -795,8 +768,7 @@
 
 // This allows reading chars from the new style of String objects during compilation.
 void UnstartedRuntime::UnstartedStringCharAt(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   jint index = shadow_frame->GetVReg(arg_offset + 1);
   mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
   if (string == nullptr) {
@@ -808,8 +780,7 @@
 
 // This allows setting chars from the new style of String objects during compilation.
 void UnstartedRuntime::UnstartedStringSetCharAt(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result ATTRIBUTE_UNUSED, size_t arg_offset) {
   jint index = shadow_frame->GetVReg(arg_offset + 1);
   jchar c = shadow_frame->GetVReg(arg_offset + 2);
   mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
@@ -822,13 +793,13 @@
 
 // This allows creating the new style of String objects during compilation.
 void UnstartedRuntime::UnstartedStringFactoryNewStringFromChars(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   jint offset = shadow_frame->GetVReg(arg_offset);
   jint char_count = shadow_frame->GetVReg(arg_offset + 1);
   DCHECK_GE(char_count, 0);
   StackHandleScope<1> hs(self);
-  Handle<mirror::CharArray> h_char_array(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray()));
+  Handle<mirror::CharArray> h_char_array(
+      hs.NewHandle(shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray()));
   Runtime* runtime = Runtime::Current();
   gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
   result->SetL(mirror::String::AllocFromCharArray<true>(self, char_count, h_char_array, offset, allocator));
@@ -836,8 +807,7 @@
 
 // This allows creating the new style of String objects during compilation.
 void UnstartedRuntime::UnstartedStringFactoryNewStringFromString(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   mirror::String* to_copy = shadow_frame->GetVRegReference(arg_offset)->AsString();
   if (to_copy == nullptr) {
     AbortTransactionOrFail(self, "StringFactory.newStringFromString with null object");
@@ -852,14 +822,14 @@
 }
 
 void UnstartedRuntime::UnstartedStringFastSubstring(
-    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   jint start = shadow_frame->GetVReg(arg_offset + 1);
   jint length = shadow_frame->GetVReg(arg_offset + 2);
   DCHECK_GE(start, 0);
   DCHECK_GE(length, 0);
   StackHandleScope<1> hs(self);
-  Handle<mirror::String> h_string(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsString()));
+  Handle<mirror::String> h_string(
+      hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsString()));
   DCHECK_LE(start, h_string->GetLength());
   DCHECK_LE(start + length, h_string->GetLength());
   Runtime* runtime = Runtime::Current();
@@ -879,12 +849,9 @@
   result->SetL(string->ToCharArray(self));
 }
 
-void UnstartedRuntime::UnstartedJNIVMRuntimeNewUnpaddedArray(Thread* self,
-                                                  mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                                  mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                                  uint32_t* args,
-                                                  JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIVMRuntimeNewUnpaddedArray(
+    Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
+    uint32_t* args, JValue* result) {
   int32_t length = args[1];
   DCHECK_GE(length, 0);
   mirror::Class* element_class = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
@@ -896,20 +863,15 @@
                                                 array_class->GetComponentSizeShift(), allocator));
 }
 
-void UnstartedRuntime::UnstartedJNIVMStackGetCallingClassLoader(Thread* self ATTRIBUTE_UNUSED,
-                                                     mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                                     mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                                     uint32_t* args ATTRIBUTE_UNUSED,
-                                                     JValue* result) {
+void UnstartedRuntime::UnstartedJNIVMStackGetCallingClassLoader(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
   result->SetL(nullptr);
 }
 
-void UnstartedRuntime::UnstartedJNIVMStackGetStackClass2(Thread* self,
-                                              mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                              mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                              uint32_t* args ATTRIBUTE_UNUSED,
-                                              JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIVMStackGetStackClass2(
+    Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
+    uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
   NthCallerVisitor visitor(self, 3);
   visitor.WalkStack();
   if (visitor.caller != nullptr) {
@@ -917,76 +879,56 @@
   }
 }
 
-void UnstartedRuntime::UnstartedJNIMathLog(Thread* self ATTRIBUTE_UNUSED,
-                                mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                uint32_t* args,
-                                JValue* result) {
+void UnstartedRuntime::UnstartedJNIMathLog(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
   JValue value;
   value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
   result->SetD(log(value.GetD()));
 }
 
-void UnstartedRuntime::UnstartedJNIMathExp(Thread* self ATTRIBUTE_UNUSED,
-                                mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                uint32_t* args,
-                                JValue* result) {
+void UnstartedRuntime::UnstartedJNIMathExp(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
   JValue value;
   value.SetJ((static_cast<uint64_t>(args[1]) << 32) | args[0]);
   result->SetD(exp(value.GetD()));
 }
 
-void UnstartedRuntime::UnstartedJNIClassGetNameNative(Thread* self,
-                                           mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                           mirror::Object* receiver,
-                                           uint32_t* args ATTRIBUTE_UNUSED,
-                                           JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIClassGetNameNative(
+    Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
+    uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
   StackHandleScope<1> hs(self);
   result->SetL(mirror::Class::ComputeName(hs.NewHandle(receiver->AsClass())));
 }
 
-void UnstartedRuntime::UnstartedJNIFloatFloatToRawIntBits(Thread* self ATTRIBUTE_UNUSED,
-                                               mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                               mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                               uint32_t* args,
-                                               JValue* result) {
+void UnstartedRuntime::UnstartedJNIFloatFloatToRawIntBits(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
   result->SetI(args[0]);
 }
 
-void UnstartedRuntime::UnstartedJNIFloatIntBitsToFloat(Thread* self ATTRIBUTE_UNUSED,
-                                            mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                            mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                            uint32_t* args,
-                                            JValue* result) {
+void UnstartedRuntime::UnstartedJNIFloatIntBitsToFloat(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
   result->SetI(args[0]);
 }
 
-void UnstartedRuntime::UnstartedJNIObjectInternalClone(Thread* self,
-                                            mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                            mirror::Object* receiver,
-                                            uint32_t* args ATTRIBUTE_UNUSED,
-                                            JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIObjectInternalClone(
+    Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
+    uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
   result->SetL(receiver->Clone(self));
 }
 
-void UnstartedRuntime::UnstartedJNIObjectNotifyAll(Thread* self,
-                                        mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                        mirror::Object* receiver,
-                                        uint32_t* args ATTRIBUTE_UNUSED,
-                                        JValue* result ATTRIBUTE_UNUSED)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIObjectNotifyAll(
+    Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
+    uint32_t* args ATTRIBUTE_UNUSED, JValue* result ATTRIBUTE_UNUSED) {
   receiver->NotifyAll(self);
 }
 
-void UnstartedRuntime::UnstartedJNIStringCompareTo(Thread* self,
-                                        mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                        mirror::Object* receiver,
-                                        uint32_t* args,
-                                        JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIStringCompareTo(
+    Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver, uint32_t* args,
+    JValue* result) {
   mirror::String* rhs = reinterpret_cast<mirror::Object*>(args[0])->AsString();
   if (rhs == nullptr) {
     AbortTransactionOrFail(self, "String.compareTo with null object");
@@ -994,42 +936,30 @@
   result->SetI(receiver->AsString()->CompareTo(rhs));
 }
 
-void UnstartedRuntime::UnstartedJNIStringIntern(Thread* self ATTRIBUTE_UNUSED,
-                                     mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                     mirror::Object* receiver,
-                                     uint32_t* args ATTRIBUTE_UNUSED,
-                                     JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIStringIntern(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
+    uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
   result->SetL(receiver->AsString()->Intern());
 }
 
-void UnstartedRuntime::UnstartedJNIStringFastIndexOf(Thread* self ATTRIBUTE_UNUSED,
-                                          mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                          mirror::Object* receiver,
-                                          uint32_t* args,
-                                          JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIStringFastIndexOf(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver,
+    uint32_t* args, JValue* result) {
   result->SetI(receiver->AsString()->FastIndexOf(args[0], args[1]));
 }
 
-void UnstartedRuntime::UnstartedJNIArrayCreateMultiArray(Thread* self,
-                                              mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                              mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                              uint32_t* args,
-                                              JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIArrayCreateMultiArray(
+    Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
+    uint32_t* args, JValue* result) {
   StackHandleScope<2> hs(self);
   auto h_class(hs.NewHandle(reinterpret_cast<mirror::Class*>(args[0])->AsClass()));
   auto h_dimensions(hs.NewHandle(reinterpret_cast<mirror::IntArray*>(args[1])->AsIntArray()));
   result->SetL(mirror::Array::CreateMultiArray(self, h_class, h_dimensions));
 }
 
-void UnstartedRuntime::UnstartedJNIArrayCreateObjectArray(Thread* self,
-                                               mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                               mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                               uint32_t* args,
-                                               JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIArrayCreateObjectArray(
+    Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
+    uint32_t* args, JValue* result) {
   int32_t length = static_cast<int32_t>(args[1]);
   if (length < 0) {
     ThrowNegativeArraySizeException(length);
@@ -1049,12 +979,9 @@
   result->SetL(new_array);
 }
 
-void UnstartedRuntime::UnstartedJNIThrowableNativeFillInStackTrace(Thread* self,
-                                                        mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                                        mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                                        uint32_t* args ATTRIBUTE_UNUSED,
-                                                        JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIThrowableNativeFillInStackTrace(
+    Thread* self, ArtMethod* method ATTRIBUTE_UNUSED, mirror::Object* receiver ATTRIBUTE_UNUSED,
+    uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
   ScopedObjectAccessUnchecked soa(self);
   if (Runtime::Current()->IsActiveTransaction()) {
     result->SetL(soa.Decode<mirror::Object*>(self->CreateInternalStackTrace<true>(soa)));
@@ -1063,30 +990,22 @@
   }
 }
 
-void UnstartedRuntime::UnstartedJNISystemIdentityHashCode(Thread* self ATTRIBUTE_UNUSED,
-                                               mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                               mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                               uint32_t* args,
-                                               JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNISystemIdentityHashCode(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
   mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
   result->SetI((obj != nullptr) ? obj->IdentityHashCode() : 0);
 }
 
-void UnstartedRuntime::UnstartedJNIByteOrderIsLittleEndian(Thread* self ATTRIBUTE_UNUSED,
-                                                mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                                mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                                uint32_t* args ATTRIBUTE_UNUSED,
-                                                JValue* result) {
+void UnstartedRuntime::UnstartedJNIByteOrderIsLittleEndian(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args ATTRIBUTE_UNUSED, JValue* result) {
   result->SetZ(JNI_TRUE);
 }
 
-void UnstartedRuntime::UnstartedJNIUnsafeCompareAndSwapInt(Thread* self ATTRIBUTE_UNUSED,
-                                                mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                                mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                                uint32_t* args,
-                                                JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIUnsafeCompareAndSwapInt(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
   mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
   jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
   jint expectedValue = args[3];
@@ -1102,12 +1021,9 @@
   result->SetZ(success ? JNI_TRUE : JNI_FALSE);
 }
 
-void UnstartedRuntime::UnstartedJNIUnsafePutObject(Thread* self ATTRIBUTE_UNUSED,
-                                        mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-                                        mirror::Object* receiver ATTRIBUTE_UNUSED,
-                                        uint32_t* args,
-                                        JValue* result ATTRIBUTE_UNUSED)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void UnstartedRuntime::UnstartedJNIUnsafePutObject(
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result ATTRIBUTE_UNUSED) {
   mirror::Object* obj = reinterpret_cast<mirror::Object*>(args[0]);
   jlong offset = (static_cast<uint64_t>(args[2]) << 32) | args[1];
   mirror::Object* newValue = reinterpret_cast<mirror::Object*>(args[3]);
@@ -1119,24 +1035,16 @@
 }
 
 void UnstartedRuntime::UnstartedJNIUnsafeGetArrayBaseOffsetForComponentType(
-    Thread* self ATTRIBUTE_UNUSED,
-    mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-    mirror::Object* receiver ATTRIBUTE_UNUSED,
-    uint32_t* args,
-    JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
   mirror::Class* component = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
   Primitive::Type primitive_type = component->GetPrimitiveType();
   result->SetI(mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value());
 }
 
 void UnstartedRuntime::UnstartedJNIUnsafeGetArrayIndexScaleForComponentType(
-    Thread* self ATTRIBUTE_UNUSED,
-    mirror::ArtMethod* method ATTRIBUTE_UNUSED,
-    mirror::Object* receiver ATTRIBUTE_UNUSED,
-    uint32_t* args,
-    JValue* result)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    Thread* self ATTRIBUTE_UNUSED, ArtMethod* method ATTRIBUTE_UNUSED,
+    mirror::Object* receiver ATTRIBUTE_UNUSED, uint32_t* args, JValue* result) {
   mirror::Class* component = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
   Primitive::Type primitive_type = component->GetPrimitiveType();
   result->SetI(Primitive::ComponentSize(primitive_type));
@@ -1145,7 +1053,7 @@
 typedef void (*InvokeHandler)(Thread* self, ShadowFrame* shadow_frame, JValue* result,
     size_t arg_size);
 
-typedef void (*JNIHandler)(Thread* self, mirror::ArtMethod* method, mirror::Object* receiver,
+typedef void (*JNIHandler)(Thread* self, ArtMethod* method, mirror::Object* receiver,
     uint32_t* args, JValue* result);
 
 static bool tables_initialized_ = false;
@@ -1200,7 +1108,7 @@
 }
 
 // Hand select a number of methods to be run in a not yet started runtime without using JNI.
-void UnstartedRuntime::Jni(Thread* self, mirror::ArtMethod* method, mirror::Object* receiver,
+void UnstartedRuntime::Jni(Thread* self, ArtMethod* method, mirror::Object* receiver,
                            uint32_t* args, JValue* result) {
   std::string name(PrettyMethod(method));
   const auto& iter = jni_handlers_.find(name);
diff --git a/runtime/interpreter/unstarted_runtime.h b/runtime/interpreter/unstarted_runtime.h
index a361af0..a357d5f 100644
--- a/runtime/interpreter/unstarted_runtime.h
+++ b/runtime/interpreter/unstarted_runtime.h
@@ -24,14 +24,12 @@
 
 namespace art {
 
+class ArtMethod;
 class Thread;
 class ShadowFrame;
 
 namespace mirror {
-
-class ArtMethod;
 class Object;
-
 }  // namespace mirror
 
 namespace interpreter {
@@ -57,7 +55,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void Jni(Thread* self,
-                  mirror::ArtMethod* method,
+                  ArtMethod* method,
                   mirror::Object* receiver,
                   uint32_t* args,
                   JValue* result)
@@ -80,7 +78,7 @@
   // Methods that are native.
 #define UNSTARTED_JNI(ShortName, SigIgnored)                       \
   static void UnstartedJNI ## ShortName(Thread* self,              \
-                                        mirror::ArtMethod* method, \
+                                        ArtMethod* method, \
                                         mirror::Object* receiver,  \
                                         uint32_t* args,            \
                                         JValue* result)            \
diff --git a/runtime/interpreter/unstarted_runtime_list.h b/runtime/interpreter/unstarted_runtime_list.h
index 8f6014c..047e9066 100644
--- a/runtime/interpreter/unstarted_runtime_list.h
+++ b/runtime/interpreter/unstarted_runtime_list.h
@@ -31,7 +31,6 @@
   V(SystemArraycopyInt, "void java.lang.System.arraycopy(int[], int, int[], int, int)") \
   V(ThreadLocalGet, "java.lang.Object java.lang.ThreadLocal.get()") \
   V(MathCeil, "double java.lang.Math.ceil(double)") \
-  V(ArtMethodGetMethodName, "java.lang.String java.lang.reflect.ArtMethod.getMethodName(java.lang.reflect.ArtMethod)") \
   V(ObjectHashCode, "int java.lang.Object.hashCode()") \
   V(DoubleDoubleToRawLongBits, "long java.lang.Double.doubleToRawLongBits(double)") \
   V(DexCacheGetDexNative, "com.android.dex.Dex java.lang.DexCache.getDexNative()") \
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 9179d17..4b672e0 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -52,9 +52,9 @@
 #undef UNSTARTED_DIRECT
 
   // Methods that are native.
-#define UNSTARTED_JNI(Name, SigIgnored)                                   \
+#define UNSTARTED_JNI(Name, SigIgnored)                       \
   static void UnstartedJNI ## Name(Thread* self,              \
-                                   mirror::ArtMethod* method, \
+                                   ArtMethod* method,         \
                                    mirror::Object* receiver,  \
                                    uint32_t* args,            \
                                    JValue* result)            \
@@ -253,7 +253,8 @@
   Thread* self = Thread::Current();
   ScopedObjectAccess soa(self);
   mirror::Class* klass = mirror::String::GetJavaLangString();
-  mirror::ArtMethod* method = klass->FindDeclaredDirectMethod("<init>", "(Ljava/lang/String;)V");
+  ArtMethod* method = klass->FindDeclaredDirectMethod("<init>", "(Ljava/lang/String;)V",
+                                                      sizeof(void*));
 
   // create instruction data for invoke-direct {v0, v1} of method with fake index
   uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 };
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index 3142089..2d3d19c 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -18,6 +18,7 @@
 
 #include <dlfcn.h>
 
+#include "art_method.h"
 #include "base/dumpable.h"
 #include "base/mutex.h"
 #include "base/stl_util.h"
@@ -25,7 +26,6 @@
 #include "dex_file-inl.h"
 #include "fault_handler.h"
 #include "indirect_reference_table-inl.h"
-#include "mirror/art_method.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "nativebridge/native_bridge.h"
@@ -205,7 +205,7 @@
   }
 
   // See section 11.3 "Linking Native Methods" of the JNI spec.
-  void* FindNativeMethod(mirror::ArtMethod* m, std::string& detail)
+  void* FindNativeMethod(ArtMethod* m, std::string& detail)
       EXCLUSIVE_LOCKS_REQUIRED(Locks::jni_libraries_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     std::string jni_short_name(JniShortName(m));
@@ -386,7 +386,7 @@
 void JavaVMExt::JniAbort(const char* jni_function_name, const char* msg) {
   Thread* self = Thread::Current();
   ScopedObjectAccess soa(self);
-  mirror::ArtMethod* current_method = self->GetCurrentMethod(nullptr);
+  ArtMethod* current_method = self->GetCurrentMethod(nullptr);
 
   std::ostringstream os;
   os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
@@ -424,7 +424,7 @@
   va_end(args);
 }
 
-bool JavaVMExt::ShouldTrace(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+bool JavaVMExt::ShouldTrace(ArtMethod* method) {
   // Fast where no tracing is enabled.
   if (trace_.empty() && !VLOG_IS_ON(third_party_jni)) {
     return false;
@@ -737,7 +737,7 @@
   return was_successful;
 }
 
-void* JavaVMExt::FindCodeForNativeMethod(mirror::ArtMethod* m) {
+void* JavaVMExt::FindCodeForNativeMethod(ArtMethod* m) {
   CHECK(m->IsNative());
   mirror::Class* c = m->GetDeclaringClass();
   // If this is a static method, it could be called before the class has been initialized.
diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h
index 594027c..4fdf45a 100644
--- a/runtime/java_vm_ext.h
+++ b/runtime/java_vm_ext.h
@@ -27,10 +27,10 @@
 namespace art {
 
 namespace mirror {
-  class ArtMethod;
   class Array;
 }  // namespace mirror
 
+class ArtMethod;
 class Libraries;
 class ParsedOptions;
 class Runtime;
@@ -77,7 +77,7 @@
   // such as NewByteArray.
   // If -verbose:third-party-jni is on, we want to log any JNI function calls
   // made by a third-party native method.
-  bool ShouldTrace(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool ShouldTrace(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   /**
    * Loads the given shared library. 'path' is an absolute pathname.
@@ -92,7 +92,7 @@
    * Returns a pointer to the code for the native method 'm', found
    * using dlsym(3) on every native library that's been loaded so far.
    */
-  void* FindCodeForNativeMethod(mirror::ArtMethod* m)
+  void* FindCodeForNativeMethod(ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void DumpForSigQuit(std::ostream& os)
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h
index 55441c9..e18d10f 100644
--- a/runtime/jdwp/jdwp.h
+++ b/runtime/jdwp/jdwp.h
@@ -34,11 +34,11 @@
 namespace art {
 
 class ArtField;
+class ArtMethod;
 union JValue;
 class Thread;
 
 namespace mirror {
-  class ArtMethod;
   class Class;
   class Object;
   class Throwable;
@@ -74,7 +74,7 @@
 static inline void expandBufAddFrameId(ExpandBuf* pReply, FrameId id) { expandBufAdd8BE(pReply, id); }
 
 struct EventLocation {
-  mirror::ArtMethod* method;
+  ArtMethod* method;
   uint32_t dex_pc;
 };
 
diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc
index ff75268..612af8b 100644
--- a/runtime/jdwp/jdwp_event.cc
+++ b/runtime/jdwp/jdwp_event.cc
@@ -22,6 +22,7 @@
 #include <unistd.h>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/stringprintf.h"
 #include "debugger.h"
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 5dc739e..bc9545b 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -18,11 +18,11 @@
 
 #include <dlfcn.h>
 
+#include "art_method-inl.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
 #include "interpreter/interpreter.h"
 #include "jit_code_cache.h"
 #include "jit_instrumentation.h"
-#include "mirror/art_method-inl.h"
 #include "runtime.h"
 #include "runtime_options.h"
 #include "thread_list.h"
@@ -100,7 +100,7 @@
     *error_msg = "JIT couldn't find jit_unload entry point";
     return false;
   }
-  jit_compile_method_ = reinterpret_cast<bool (*)(void*, mirror::ArtMethod*, Thread*)>(
+  jit_compile_method_ = reinterpret_cast<bool (*)(void*, ArtMethod*, Thread*)>(
       dlsym(jit_library_handle_, "jit_compile_method"));
   if (jit_compile_method_ == nullptr) {
     dlclose(jit_library_handle_);
@@ -126,7 +126,7 @@
   return true;
 }
 
-bool Jit::CompileMethod(mirror::ArtMethod* method, Thread* self) {
+bool Jit::CompileMethod(ArtMethod* method, Thread* self) {
   DCHECK(!method->IsRuntimeMethod());
   if (Dbg::IsDebuggerActive() && Dbg::MethodHasAnyBreakpoints(method)) {
     VLOG(jit) << "JIT not compiling " << PrettyMethod(method) << " due to breakpoint";
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 8f92453..dbd8977 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -30,13 +30,10 @@
 
 namespace art {
 
+class ArtMethod;
 class CompilerCallbacks;
 struct RuntimeArgumentMap;
 
-namespace mirror {
-class ArtMethod;
-}  // namespace mirror
-
 namespace jit {
 
 class JitCodeCache;
@@ -50,7 +47,7 @@
 
   virtual ~Jit();
   static Jit* Create(JitOptions* options, std::string* error_msg);
-  bool CompileMethod(mirror::ArtMethod* method, Thread* self)
+  bool CompileMethod(ArtMethod* method, Thread* self)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void CreateInstrumentationCache(size_t compile_threshold);
   void CreateThreadPool();
@@ -79,7 +76,7 @@
   void* jit_compiler_handle_;
   void* (*jit_load_)(CompilerCallbacks**);
   void (*jit_unload_)(void*);
-  bool (*jit_compile_method_)(void*, mirror::ArtMethod*, Thread*);
+  bool (*jit_compile_method_)(void*, ArtMethod*, Thread*);
 
   // Performance monitoring.
   bool dump_info_on_shutdown_;
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 4d367e0..cd5f4cb 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -18,8 +18,8 @@
 
 #include <sstream>
 
+#include "art_method-inl.h"
 #include "mem_map.h"
-#include "mirror/art_method-inl.h"
 #include "oat_file-inl.h"
 
 namespace art {
@@ -58,7 +58,7 @@
   code_cache_end_ = mem_map->End();
 }
 
-bool JitCodeCache::ContainsMethod(mirror::ArtMethod* method) const {
+bool JitCodeCache::ContainsMethod(ArtMethod* method) const {
   return ContainsCodePtr(method->GetEntryPointFromQuickCompiledCode());
 }
 
@@ -93,7 +93,7 @@
   return data_cache_ptr_ - size;
 }
 
-const void* JitCodeCache::GetCodeFor(mirror::ArtMethod* method) {
+const void* JitCodeCache::GetCodeFor(ArtMethod* method) {
   const void* code = method->GetEntryPointFromQuickCompiledCode();
   if (ContainsCodePtr(code)) {
     return code;
@@ -106,7 +106,7 @@
   return nullptr;
 }
 
-void JitCodeCache::SaveCompiledCode(mirror::ArtMethod* method, const void* old_code_ptr) {
+void JitCodeCache::SaveCompiledCode(ArtMethod* method, const void* old_code_ptr) {
   DCHECK_EQ(method->GetEntryPointFromQuickCompiledCode(), old_code_ptr);
   DCHECK(ContainsCodePtr(old_code_ptr)) << PrettyMethod(method) << " old_code_ptr="
       << old_code_ptr;
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index 8b76647..c1ea921 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -31,13 +31,10 @@
 
 namespace art {
 
+class ArtMethod;
 class CompiledMethod;
 class CompilerCallbacks;
 
-namespace mirror {
-class ArtMethod;
-}  // namespcae mirror
-
 namespace jit {
 
 class JitInstrumentationCache;
@@ -80,7 +77,7 @@
   }
 
   // Return true if the code cache contains the code pointer which si the entrypoint of the method.
-  bool ContainsMethod(mirror::ArtMethod* method) const
+  bool ContainsMethod(ArtMethod* method) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Return true if the code cache contains a code ptr.
@@ -95,12 +92,12 @@
       LOCKS_EXCLUDED(lock_);
 
   // Get code for a method, returns null if it is not in the jit cache.
-  const void* GetCodeFor(mirror::ArtMethod* method)
+  const void* GetCodeFor(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(lock_);
 
   // Save the compiled code for a method so that GetCodeFor(method) will return old_code_ptr if the
   // entrypoint isn't within the cache.
-  void SaveCompiledCode(mirror::ArtMethod* method, const void* old_code_ptr)
+  void SaveCompiledCode(ArtMethod* method, const void* old_code_ptr)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(lock_);
 
  private:
@@ -125,10 +122,9 @@
   const uint8_t* data_cache_begin_;
   const uint8_t* data_cache_end_;
   size_t num_methods_;
-  // TODO: This relies on methods not moving.
   // This map holds code for methods if they were deoptimized by the instrumentation stubs. This is
   // required since we have to implement ClassLinker::GetQuickOatCodeFor for walking stacks.
-  SafeMap<mirror::ArtMethod*, const void*> method_code_map_ GUARDED_BY(lock_);
+  SafeMap<ArtMethod*, const void*> method_code_map_ GUARDED_BY(lock_);
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(JitCodeCache);
 };
diff --git a/runtime/jit/jit_code_cache_test.cc b/runtime/jit/jit_code_cache_test.cc
index afa5a3e..cd123b9 100644
--- a/runtime/jit/jit_code_cache_test.cc
+++ b/runtime/jit/jit_code_cache_test.cc
@@ -16,9 +16,9 @@
 
 #include "common_runtime_test.h"
 
+#include "art_method-inl.h"
 #include "class_linker.h"
 #include "jit_code_cache.h"
-#include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 #include "thread-inl.h"
 
@@ -50,15 +50,15 @@
   ASSERT_TRUE(code_cache->ContainsCodePtr(reserved_code));
   ASSERT_EQ(code_cache->NumMethods(), 1u);
   ClassLinker* const cl = Runtime::Current()->GetClassLinker();
-  auto h_method = hs.NewHandle(cl->AllocArtMethod(soa.Self()));
-  ASSERT_FALSE(code_cache->ContainsMethod(h_method.Get()));
-  h_method->SetEntryPointFromQuickCompiledCode(reserved_code);
-  ASSERT_TRUE(code_cache->ContainsMethod(h_method.Get()));
-  ASSERT_EQ(code_cache->GetCodeFor(h_method.Get()), reserved_code);
+  auto* method = cl->AllocArtMethodArray(soa.Self(), 1);
+  ASSERT_FALSE(code_cache->ContainsMethod(method));
+  method->SetEntryPointFromQuickCompiledCode(reserved_code);
+  ASSERT_TRUE(code_cache->ContainsMethod(method));
+  ASSERT_EQ(code_cache->GetCodeFor(method), reserved_code);
   // Save the code and then change it.
-  code_cache->SaveCompiledCode(h_method.Get(), reserved_code);
-  h_method->SetEntryPointFromQuickCompiledCode(nullptr);
-  ASSERT_EQ(code_cache->GetCodeFor(h_method.Get()), reserved_code);
+  code_cache->SaveCompiledCode(method, reserved_code);
+  method->SetEntryPointFromQuickCompiledCode(nullptr);
+  ASSERT_EQ(code_cache->GetCodeFor(method), reserved_code);
   const uint8_t data_arr[] = {1, 2, 3, 4, 5};
   uint8_t* data_ptr = code_cache->AddDataArray(soa.Self(), data_arr, data_arr + sizeof(data_arr));
   ASSERT_TRUE(data_ptr != nullptr);
@@ -76,7 +76,8 @@
   size_t data_bytes = 0;
   constexpr size_t kCodeArrSize = 4 * KB;
   constexpr size_t kDataArrSize = 4 * KB;
-  uint8_t data_arr[kDataArrSize] = {53};
+  uint8_t data_arr[kDataArrSize];
+  std::fill_n(data_arr, arraysize(data_arr), 53);
   // Add code and data until we are full.
   uint8_t* code_ptr = nullptr;
   uint8_t* data_ptr = nullptr;
diff --git a/runtime/jit/jit_instrumentation.cc b/runtime/jit/jit_instrumentation.cc
index 3232674..1e56cdc 100644
--- a/runtime/jit/jit_instrumentation.cc
+++ b/runtime/jit/jit_instrumentation.cc
@@ -16,9 +16,9 @@
 
 #include "jit_instrumentation.h"
 
+#include "art_method-inl.h"
 #include "jit.h"
 #include "jit_code_cache.h"
-#include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 
 namespace art {
@@ -26,7 +26,7 @@
 
 class JitCompileTask : public Task {
  public:
-  explicit JitCompileTask(mirror::ArtMethod* method, JitInstrumentationCache* cache)
+  explicit JitCompileTask(ArtMethod* method, JitInstrumentationCache* cache)
       : method_(method), cache_(cache) {
   }
 
@@ -45,7 +45,7 @@
   }
 
  private:
-  mirror::ArtMethod* const method_;
+  ArtMethod* const method_;
   JitInstrumentationCache* const cache_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(JitCompileTask);
@@ -63,7 +63,7 @@
   thread_pool_.reset();
 }
 
-void JitInstrumentationCache::SignalCompiled(Thread* self, mirror::ArtMethod* method) {
+void JitInstrumentationCache::SignalCompiled(Thread* self, ArtMethod* method) {
   ScopedObjectAccessUnchecked soa(self);
   jmethodID method_id = soa.EncodeMethod(method);
   MutexLock mu(self, lock_);
@@ -73,7 +73,7 @@
   }
 }
 
-void JitInstrumentationCache::AddSamples(Thread* self, mirror::ArtMethod* method, size_t count) {
+void JitInstrumentationCache::AddSamples(Thread* self, ArtMethod* method, size_t count) {
   ScopedObjectAccessUnchecked soa(self);
   // Since we don't have on-stack replacement, some methods can remain in the interpreter longer
   // than we want resulting in samples even after the method is compiled.
@@ -101,11 +101,13 @@
   }
   if (is_hot) {
     if (thread_pool_.get() != nullptr) {
-      thread_pool_->AddTask(self, new JitCompileTask(method->GetInterfaceMethodIfProxy(), this));
+      thread_pool_->AddTask(self, new JitCompileTask(
+          method->GetInterfaceMethodIfProxy(sizeof(void*)), this));
       thread_pool_->StartWorkers(self);
     } else {
       VLOG(jit) << "Compiling hot method " << PrettyMethod(method);
-      Runtime::Current()->GetJit()->CompileMethod(method->GetInterfaceMethodIfProxy(), self);
+      Runtime::Current()->GetJit()->CompileMethod(
+          method->GetInterfaceMethodIfProxy(sizeof(void*)), self);
     }
   }
 }
diff --git a/runtime/jit/jit_instrumentation.h b/runtime/jit/jit_instrumentation.h
index 72acaef..27894eb 100644
--- a/runtime/jit/jit_instrumentation.h
+++ b/runtime/jit/jit_instrumentation.h
@@ -31,12 +31,12 @@
 
 namespace art {
 namespace mirror {
-  class ArtMethod;
   class Class;
   class Object;
   class Throwable;
 }  // namespace mirror
 class ArtField;
+class ArtMethod;
 union JValue;
 class Thread;
 
@@ -46,9 +46,9 @@
 class JitInstrumentationCache {
  public:
   explicit JitInstrumentationCache(size_t hot_method_threshold);
-  void AddSamples(Thread* self, mirror::ArtMethod* method, size_t samples)
+  void AddSamples(Thread* self, ArtMethod* method, size_t samples)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  void SignalCompiled(Thread* self, mirror::ArtMethod* method)
+  void SignalCompiled(Thread* self, ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void CreateThreadPool();
   void DeleteThreadPool();
@@ -67,31 +67,31 @@
   explicit JitInstrumentationListener(JitInstrumentationCache* cache);
 
   virtual void MethodEntered(Thread* thread, mirror::Object* /*this_object*/,
-                             mirror::ArtMethod* method, uint32_t /*dex_pc*/)
+                             ArtMethod* method, uint32_t /*dex_pc*/)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     instrumentation_cache_->AddSamples(thread, method, 1);
   }
   virtual void MethodExited(Thread* /*thread*/, mirror::Object* /*this_object*/,
-                            mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/,
+                            ArtMethod* /*method*/, uint32_t /*dex_pc*/,
                             const JValue& /*return_value*/)
       OVERRIDE { }
   virtual void MethodUnwind(Thread* /*thread*/, mirror::Object* /*this_object*/,
-                            mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/) OVERRIDE { }
+                            ArtMethod* /*method*/, uint32_t /*dex_pc*/) OVERRIDE { }
   virtual void FieldRead(Thread* /*thread*/, mirror::Object* /*this_object*/,
-                         mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/,
+                         ArtMethod* /*method*/, uint32_t /*dex_pc*/,
                          ArtField* /*field*/) OVERRIDE { }
   virtual void FieldWritten(Thread* /*thread*/, mirror::Object* /*this_object*/,
-                            mirror::ArtMethod* /*method*/, uint32_t /*dex_pc*/,
+                            ArtMethod* /*method*/, uint32_t /*dex_pc*/,
                             ArtField* /*field*/, const JValue& /*field_value*/)
       OVERRIDE { }
   virtual void ExceptionCaught(Thread* /*thread*/,
                                mirror::Throwable* /*exception_object*/) OVERRIDE { }
 
   virtual void DexPcMoved(Thread* /*self*/, mirror::Object* /*this_object*/,
-                          mirror::ArtMethod* /*method*/, uint32_t /*new_dex_pc*/) OVERRIDE { }
+                          ArtMethod* /*method*/, uint32_t /*new_dex_pc*/) OVERRIDE { }
 
   // We only care about how many dex instructions were executed in the Jit.
-  virtual void BackwardBranch(Thread* thread, mirror::ArtMethod* method, int32_t dex_pc_offset)
+  virtual void BackwardBranch(Thread* thread, ArtMethod* method, int32_t dex_pc_offset)
       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     CHECK_LE(dex_pc_offset, 0);
     instrumentation_cache_->AddSamples(thread, method, 1);
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index f435467..6ab4455 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -24,6 +24,7 @@
 #include <vector>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "atomic.h"
 #include "base/allocator.h"
 #include "base/logging.h"
@@ -38,7 +39,6 @@
 #include "interpreter/interpreter.h"
 #include "jni_env_ext.h"
 #include "java_vm_ext.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/field-inl.h"
@@ -126,17 +126,18 @@
   if (c == nullptr) {
     return nullptr;
   }
-  mirror::ArtMethod* method = nullptr;
+  ArtMethod* method = nullptr;
+  auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
   if (is_static) {
-    method = c->FindDirectMethod(name, sig);
+    method = c->FindDirectMethod(name, sig, pointer_size);
   } else if (c->IsInterface()) {
-    method = c->FindInterfaceMethod(name, sig);
+    method = c->FindInterfaceMethod(name, sig, pointer_size);
   } else {
-    method = c->FindVirtualMethod(name, sig);
+    method = c->FindVirtualMethod(name, sig, pointer_size);
     if (method == nullptr) {
       // No virtual method matching the signature.  Search declared
       // private methods and constructors.
-      method = c->FindDeclaredDirectMethod(name, sig);
+      method = c->FindDeclaredDirectMethod(name, sig, pointer_size);
     }
   }
   if (method == nullptr || method->IsStatic() != is_static) {
@@ -148,7 +149,7 @@
 
 static mirror::ClassLoader* GetClassLoader(const ScopedObjectAccess& soa)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ArtMethod* method = soa.Self()->GetCurrentMethod(nullptr);
+  ArtMethod* method = soa.Self()->GetCurrentMethod(nullptr);
   // If we are running Runtime.nativeLoad, use the overriding ClassLoader it set.
   if (method == soa.DecodeMethod(WellKnownClasses::java_lang_Runtime_nativeLoad)) {
     return soa.Decode<mirror::ClassLoader*>(soa.Self()->GetClassLoaderOverride());
@@ -312,26 +313,19 @@
   }
 
 template <bool kNative>
-static mirror::ArtMethod* FindMethod(mirror::Class* c,
-                                     const StringPiece& name,
-                                     const StringPiece& sig)
+static ArtMethod* FindMethod(mirror::Class* c, const StringPiece& name, const StringPiece& sig)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
-    mirror::ArtMethod* method = c->GetDirectMethod(i);
-    if (kNative == method->IsNative() &&
-        name == method->GetName() && method->GetSignature() == sig) {
-      return method;
+  auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+  for (auto& method : c->GetDirectMethods(pointer_size)) {
+    if (kNative == method.IsNative() && name == method.GetName() && method.GetSignature() == sig) {
+      return &method;
     }
   }
-
-  for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
-    mirror::ArtMethod* method = c->GetVirtualMethod(i);
-    if (kNative == method->IsNative() &&
-        name == method->GetName() && method->GetSignature() == sig) {
-      return method;
+  for (auto& method : c->GetVirtualMethods(pointer_size)) {
+    if (kNative == method.IsNative() && name == method.GetName() && method.GetSignature() == sig) {
+      return &method;
     }
   }
-
   return nullptr;
 }
 
@@ -366,7 +360,7 @@
   static jmethodID FromReflectedMethod(JNIEnv* env, jobject jlr_method) {
     CHECK_NON_NULL_ARGUMENT(jlr_method);
     ScopedObjectAccess soa(env);
-    return soa.EncodeMethod(mirror::ArtMethod::FromReflectedMethod(soa, jlr_method));
+    return soa.EncodeMethod(ArtMethod::FromReflectedMethod(soa, jlr_method));
   }
 
   static jfieldID FromReflectedField(JNIEnv* env, jobject jlr_field) {
@@ -384,8 +378,7 @@
   static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
     CHECK_NON_NULL_ARGUMENT(mid);
     ScopedObjectAccess soa(env);
-    mirror::ArtMethod* m = soa.DecodeMethod(mid);
-    CHECK(!kMovingMethods);
+    ArtMethod* m = soa.DecodeMethod(mid);
     mirror::AbstractMethod* method;
     if (m->IsConstructor()) {
       method = mirror::Constructor::CreateFromArtMethod(soa.Self(), m);
@@ -2151,7 +2144,7 @@
       // Note: the right order is to try to find the method locally
       // first, either as a direct or a virtual method. Then move to
       // the parent.
-      mirror::ArtMethod* m = nullptr;
+      ArtMethod* m = nullptr;
       bool warn_on_going_to_parent = down_cast<JNIEnvExt*>(env)->vm->IsCheckJniEnabled();
       for (mirror::Class* current_class = c;
            current_class != nullptr;
@@ -2207,17 +2200,16 @@
     VLOG(jni) << "[Unregistering JNI native methods for " << PrettyClass(c) << "]";
 
     size_t unregistered_count = 0;
-    for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
-      mirror::ArtMethod* m = c->GetDirectMethod(i);
-      if (m->IsNative()) {
-        m->UnregisterNative();
+    auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+    for (auto& m : c->GetDirectMethods(pointer_size)) {
+      if (m.IsNative()) {
+        m.UnregisterNative();
         unregistered_count++;
       }
     }
-    for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
-      mirror::ArtMethod* m = c->GetVirtualMethod(i);
-      if (m->IsNative()) {
-        m->UnregisterNative();
+    for (auto& m : c->GetVirtualMethods(pointer_size)) {
+      if (m.IsNative()) {
+        m.UnregisterNative();
         unregistered_count++;
       }
     }
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index 581ef0e..99eb365 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -16,9 +16,9 @@
 
 #include "jni_internal.h"
 
+#include "art_method-inl.h"
 #include "common_compiler_test.h"
 #include "java_vm_ext.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/string-inl.h"
 #include "scoped_thread_state_change.h"
 #include "ScopedLocalRef.h"
diff --git a/runtime/linear_alloc.cc b/runtime/linear_alloc.cc
index fe6bee6..43e81d9 100644
--- a/runtime/linear_alloc.cc
+++ b/runtime/linear_alloc.cc
@@ -23,6 +23,11 @@
 LinearAlloc::LinearAlloc(ArenaPool* pool) : lock_("linear alloc"), allocator_(pool) {
 }
 
+void* LinearAlloc::Realloc(Thread* self, void* ptr, size_t old_size, size_t new_size) {
+  MutexLock mu(self, lock_);
+  return allocator_.Realloc(ptr, old_size, new_size);
+}
+
 void* LinearAlloc::Alloc(Thread* self, size_t size) {
   MutexLock mu(self, lock_);
   return allocator_.Alloc(size);
@@ -33,4 +38,14 @@
   return allocator_.BytesUsed();
 }
 
+ArenaPool* LinearAlloc::GetArenaPool() {
+  MutexLock mu(Thread::Current(), lock_);
+  return allocator_.GetArenaPool();
+}
+
+bool LinearAlloc::Contains(void* ptr) const {
+  MutexLock mu(Thread::Current(), lock_);
+  return allocator_.Contains(ptr);
+}
+
 }  // namespace art
diff --git a/runtime/linear_alloc.h b/runtime/linear_alloc.h
index fcabcc8..c10ddfd 100644
--- a/runtime/linear_alloc.h
+++ b/runtime/linear_alloc.h
@@ -28,7 +28,10 @@
  public:
   explicit LinearAlloc(ArenaPool* pool);
 
-  void* Alloc(Thread* self, size_t size);
+  void* Alloc(Thread* self, size_t size) LOCKS_EXCLUDED(lock_);
+
+  // Realloc never frees the input pointer, it is the caller's job to do this if necessary.
+  void* Realloc(Thread* self, void* ptr, size_t old_size, size_t new_size) LOCKS_EXCLUDED(lock_);
 
   // Allocate and construct an array of structs of type T.
   template<class T>
@@ -37,7 +40,12 @@
   }
 
   // Return the number of bytes used in the allocator.
-  size_t GetUsedMemory() const;
+  size_t GetUsedMemory() const LOCKS_EXCLUDED(lock_);
+
+  ArenaPool* GetArenaPool() LOCKS_EXCLUDED(lock_);
+
+  // Return true if the linear alloc contrains an address.
+  bool Contains(void* ptr) const;
 
  private:
   mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
diff --git a/runtime/mirror/abstract_method.cc b/runtime/mirror/abstract_method.cc
index 81c656b..91a9870 100644
--- a/runtime/mirror/abstract_method.cc
+++ b/runtime/mirror/abstract_method.cc
@@ -16,14 +16,14 @@
 
 #include "abstract_method.h"
 
-#include "mirror/art_method-inl.h"
+#include "art_method-inl.h"
 
 namespace art {
 namespace mirror {
 
-bool AbstractMethod::CreateFromArtMethod(mirror::ArtMethod* method) {
-  auto* interface_method = method->GetInterfaceMethodIfProxy();
-  SetFieldObject<false>(ArtMethodOffset(), method);
+bool AbstractMethod::CreateFromArtMethod(ArtMethod* method) {
+  auto* interface_method = method->GetInterfaceMethodIfProxy(sizeof(void*));
+  SetArtMethod(method);
   SetFieldObject<false>(DeclaringClassOffset(), method->GetDeclaringClass());
   SetFieldObject<false>(
       DeclaringClassOfOverriddenMethodOffset(), interface_method->GetDeclaringClass());
@@ -32,8 +32,12 @@
   return true;
 }
 
-mirror::ArtMethod* AbstractMethod::GetArtMethod() {
-  return GetFieldObject<mirror::ArtMethod>(ArtMethodOffset());
+ArtMethod* AbstractMethod::GetArtMethod() {
+  return reinterpret_cast<ArtMethod*>(GetField64(ArtMethodOffset()));
+}
+
+void AbstractMethod::SetArtMethod(ArtMethod* method) {
+  SetField64<false>(ArtMethodOffset(), reinterpret_cast<uint64_t>(method));
 }
 
 mirror::Class* AbstractMethod::GetDeclaringClass() {
diff --git a/runtime/mirror/abstract_method.h b/runtime/mirror/abstract_method.h
index ef51d7f..99d697a 100644
--- a/runtime/mirror/abstract_method.h
+++ b/runtime/mirror/abstract_method.h
@@ -26,18 +26,19 @@
 namespace art {
 
 struct AbstractMethodOffsets;
+class ArtMethod;
 
 namespace mirror {
 
-class ArtMethod;
-
 // C++ mirror of java.lang.reflect.AbstractMethod.
 class MANAGED AbstractMethod : public AccessibleObject {
  public:
   // Called from Constructor::CreateFromArtMethod, Method::CreateFromArtMethod.
-  bool CreateFromArtMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool CreateFromArtMethod(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtMethod* GetArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* GetArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  // Only used by the image writer.
+  void SetArtMethod(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
  private:
@@ -57,9 +58,10 @@
     return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, dex_method_index_));
   }
 
-  HeapReference<mirror::ArtMethod> art_method_;
   HeapReference<mirror::Class> declaring_class_;
   HeapReference<mirror::Class> declaring_class_of_overridden_method_;
+  uint32_t padding_;
+  uint64_t art_method_;
   uint32_t access_flags_;
   uint32_t dex_method_index_;
 
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index f3546b1..88d75ab 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -20,19 +20,19 @@
 #include "array.h"
 
 #include "base/bit_utils.h"
+#include "base/casts.h"
 #include "base/logging.h"
 #include "base/stringprintf.h"
-#include "base/casts.h"
-#include "class.h"
+#include "class-inl.h"
 #include "gc/heap-inl.h"
 #include "thread.h"
 
 namespace art {
 namespace mirror {
 
-inline uint32_t Array::ClassSize() {
+inline uint32_t Array::ClassSize(size_t pointer_size) {
   uint32_t vtable_entries = Object::kVTableLength;
-  return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
+  return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
 }
 
 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
@@ -371,6 +371,30 @@
   }
 }
 
+template<typename T>
+inline T PointerArray::GetElementPtrSize(uint32_t idx, size_t ptr_size) {
+  // C style casts here since we sometimes have T be a pointer, or sometimes an integer
+  // (for stack traces).
+  if (ptr_size == 8) {
+    return (T)static_cast<uintptr_t>(AsLongArray()->GetWithoutChecks(idx));
+  }
+  DCHECK_EQ(ptr_size, 4u);
+  return (T)static_cast<uintptr_t>(AsIntArray()->GetWithoutChecks(idx));
+}
+
+template<bool kTransactionActive, bool kUnchecked, typename T>
+inline void PointerArray::SetElementPtrSize(uint32_t idx, T element, size_t ptr_size) {
+  if (ptr_size == 8) {
+    (kUnchecked ? down_cast<LongArray*>(static_cast<Object*>(this)) : AsLongArray())->
+        SetWithoutChecks<kTransactionActive>(idx, (uint64_t)(element));
+  } else {
+    DCHECK_EQ(ptr_size, 4u);
+    DCHECK_LE((uintptr_t)element, 0xFFFFFFFFu);
+    (kUnchecked ? down_cast<IntArray*>(static_cast<Object*>(this)) : AsIntArray())
+        ->SetWithoutChecks<kTransactionActive>(idx, static_cast<uint32_t>((uintptr_t)element));
+  }
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index b92f017..d72c03f 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -125,6 +125,26 @@
   art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
 }
 
+Array* Array::CopyOf(Thread* self, int32_t new_length) {
+  CHECK(GetClass()->GetComponentType()->IsPrimitive()) << "Will miss write barriers";
+  DCHECK_GE(new_length, 0);
+  // We may get copied by a compacting GC.
+  StackHandleScope<1> hs(self);
+  auto h_this(hs.NewHandle(this));
+  auto* heap = Runtime::Current()->GetHeap();
+  gc::AllocatorType allocator_type = heap->IsMovableObject(this) ? heap->GetCurrentAllocator() :
+      heap->GetCurrentNonMovingAllocator();
+  const auto component_size = GetClass()->GetComponentSize();
+  const auto component_shift = GetClass()->GetComponentSizeShift();
+  Array* new_array = Alloc<true>(self, GetClass(), new_length, component_shift, allocator_type);
+  if (LIKELY(new_array != nullptr)) {
+    memcpy(new_array->GetRawData(component_size, 0), h_this->GetRawData(component_size, 0),
+           std::min(h_this->GetLength(), new_length) << component_shift);
+  }
+  return new_array;
+}
+
+
 template <typename T> GcRoot<Class> PrimitiveArray<T>::array_class_;
 
 // Explicitly instantiate all the primitive array types.
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 167f824..e65611d 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -31,7 +31,7 @@
 class MANAGED Array : public Object {
  public:
   // The size of a java.lang.Class representing an array.
-  static uint32_t ClassSize();
+  static uint32_t ClassSize(size_t pointer_size);
 
   // Allocates an array with the given properties, if kFillUsable is true the array will be of at
   // least component_count size, however, if there's usable space at the end of the allocation the
@@ -84,6 +84,8 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ALWAYS_INLINE bool CheckIsValidIndex(int32_t index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  Array* CopyOf(Thread* self, int32_t new_length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  protected:
   void ThrowArrayStoreException(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -176,6 +178,18 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray);
 };
 
+// Either an IntArray or a LongArray.
+class PointerArray : public Array {
+ public:
+  template<typename T>
+  T GetElementPtrSize(uint32_t idx, size_t ptr_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<bool kTransactionActive = false, bool kUnchecked = false, typename T>
+  void SetElementPtrSize(uint32_t idx, T element, size_t ptr_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+};
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 5752a15..835b94a 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -20,6 +20,7 @@
 #include "class.h"
 
 #include "art_field-inl.h"
+#include "art_method.h"
 #include "art_method-inl.h"
 #include "class_loader.h"
 #include "common_throws.h"
@@ -60,130 +61,157 @@
   return GetFieldObject<DexCache, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_));
 }
 
-inline ObjectArray<ArtMethod>* Class::GetDirectMethods() {
+inline ArtMethod* Class::GetDirectMethodsPtr() {
   DCHECK(IsLoaded() || IsErroneous());
-  return GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_));
+  return GetDirectMethodsPtrUnchecked();
 }
 
-inline void Class::SetDirectMethods(ObjectArray<ArtMethod>* new_direct_methods)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  DCHECK(nullptr == GetFieldObject<ObjectArray<ArtMethod>>(
-      OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_)));
-  DCHECK_NE(0, new_direct_methods->GetLength());
-  SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), new_direct_methods);
+inline ArtMethod* Class::GetDirectMethodsPtrUnchecked() {
+  return reinterpret_cast<ArtMethod*>(GetField64(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_)));
 }
 
-inline ArtMethod* Class::GetDirectMethod(int32_t i) {
-  return GetDirectMethods()->Get(i);
+inline ArtMethod* Class::GetVirtualMethodsPtrUnchecked() {
+  return reinterpret_cast<ArtMethod*>(GetField64(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_)));
 }
 
-inline void Class::SetDirectMethod(uint32_t i, ArtMethod* f)  // TODO: uint16_t
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ObjectArray<ArtMethod>* direct_methods =
-      GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_));
-  direct_methods->Set<false>(i, f);
+inline void Class::SetDirectMethodsPtr(ArtMethod* new_direct_methods) {
+  DCHECK(GetDirectMethodsPtrUnchecked() == nullptr);
+  SetDirectMethodsPtrUnchecked(new_direct_methods);
 }
 
-// Returns the number of static, private, and constructor methods.
-inline uint32_t Class::NumDirectMethods() {
-  return (GetDirectMethods() != nullptr) ? GetDirectMethods()->GetLength() : 0;
+inline void Class::SetDirectMethodsPtrUnchecked(ArtMethod* new_direct_methods) {
+  SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_),
+                    reinterpret_cast<uint64_t>(new_direct_methods));
+}
+
+inline ArtMethod* Class::GetDirectMethodUnchecked(size_t i, size_t pointer_size) {
+  CheckPointerSize(pointer_size);
+  auto* methods = GetDirectMethodsPtrUnchecked();
+  DCHECK(methods != nullptr);
+  return reinterpret_cast<ArtMethod*>(reinterpret_cast<uintptr_t>(methods) +
+      ArtMethod::ObjectSize(pointer_size) * i);
+}
+
+inline ArtMethod* Class::GetDirectMethod(size_t i, size_t pointer_size) {
+  CheckPointerSize(pointer_size);
+  auto* methods = GetDirectMethodsPtr();
+  DCHECK(methods != nullptr);
+  return reinterpret_cast<ArtMethod*>(reinterpret_cast<uintptr_t>(methods) +
+      ArtMethod::ObjectSize(pointer_size) * i);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline ObjectArray<ArtMethod>* Class::GetVirtualMethods() {
-  DCHECK(IsLoaded() || IsErroneous());
-  return GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_));
+inline ArtMethod* Class::GetVirtualMethodsPtr() {
+  DCHECK(IsLoaded<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
+  return GetVirtualMethodsPtrUnchecked();
 }
 
-inline void Class::SetVirtualMethods(ObjectArray<ArtMethod>* new_virtual_methods) {
+inline void Class::SetVirtualMethodsPtr(ArtMethod* new_virtual_methods) {
   // TODO: we reassign virtual methods to grow the table for miranda
   // methods.. they should really just be assigned once.
-  DCHECK_NE(0, new_virtual_methods->GetLength());
-  SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), new_virtual_methods);
-}
-
-inline uint32_t Class::NumVirtualMethods() {
-  return (GetVirtualMethods() != nullptr) ? GetVirtualMethods()->GetLength() : 0;
+  SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_),
+                    reinterpret_cast<uint64_t>(new_virtual_methods));
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline ArtMethod* Class::GetVirtualMethod(uint32_t i) {
+inline ArtMethod* Class::GetVirtualMethod(size_t i, size_t pointer_size) {
+  CheckPointerSize(pointer_size);
   DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>())
       << PrettyClass(this) << " status=" << GetStatus();
-  return GetVirtualMethods()->GetWithoutChecks(i);
+  return GetVirtualMethodUnchecked(i, pointer_size);
 }
 
-inline ArtMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) {
+inline ArtMethod* Class::GetVirtualMethodDuringLinking(size_t i, size_t pointer_size) {
+  CheckPointerSize(pointer_size);
   DCHECK(IsLoaded() || IsErroneous());
-  return GetVirtualMethods()->GetWithoutChecks(i);
+  return GetVirtualMethodUnchecked(i, pointer_size);
 }
 
-inline void Class::SetVirtualMethod(uint32_t i, ArtMethod* f)  // TODO: uint16_t
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ObjectArray<ArtMethod>* virtual_methods =
-      GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_));
-  virtual_methods->SetWithoutChecks<false>(i, f);
+inline ArtMethod* Class::GetVirtualMethodUnchecked(size_t i, size_t pointer_size) {
+  CheckPointerSize(pointer_size);
+  auto* methods = GetVirtualMethodsPtrUnchecked();
+  DCHECK(methods != nullptr);
+  return reinterpret_cast<ArtMethod*>(reinterpret_cast<uintptr_t>(methods) +
+      ArtMethod::ObjectSize(pointer_size) * i);
 }
 
-inline ObjectArray<ArtMethod>* Class::GetVTable() {
+inline PointerArray* Class::GetVTable() {
   DCHECK(IsResolved() || IsErroneous());
-  return GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
+  return GetFieldObject<PointerArray>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
 }
 
-inline ObjectArray<ArtMethod>* Class::GetVTableDuringLinking() {
+inline PointerArray* Class::GetVTableDuringLinking() {
   DCHECK(IsLoaded() || IsErroneous());
-  return GetFieldObject<ObjectArray<ArtMethod>>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
+  return GetFieldObject<PointerArray>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
 }
 
-inline void Class::SetVTable(ObjectArray<ArtMethod>* new_vtable) {
+inline void Class::SetVTable(PointerArray* new_vtable) {
   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable);
 }
 
-inline ArtMethod* Class::GetEmbeddedImTableEntry(uint32_t i) {
-  uint32_t offset = EmbeddedImTableOffset().Uint32Value() + i * sizeof(ImTableEntry);
-  return GetFieldObject<mirror::ArtMethod>(MemberOffset(offset));
+inline MemberOffset Class::EmbeddedImTableEntryOffset(uint32_t i, size_t pointer_size) {
+  DCHECK_LT(i, kImtSize);
+  return MemberOffset(
+      EmbeddedImTableOffset(pointer_size).Uint32Value() + i * ImTableEntrySize(pointer_size));
 }
 
-inline void Class::SetEmbeddedImTableEntry(uint32_t i, ArtMethod* method) {
-  uint32_t offset = EmbeddedImTableOffset().Uint32Value() + i * sizeof(ImTableEntry);
-  SetFieldObject<false>(MemberOffset(offset), method);
+inline ArtMethod* Class::GetEmbeddedImTableEntry(uint32_t i, size_t pointer_size) {
+  DCHECK(ShouldHaveEmbeddedImtAndVTable());
+  return GetFieldPtrWithSize<ArtMethod*>(
+      EmbeddedImTableEntryOffset(i, pointer_size), pointer_size);
+}
+
+inline void Class::SetEmbeddedImTableEntry(uint32_t i, ArtMethod* method, size_t pointer_size) {
+  DCHECK(ShouldHaveEmbeddedImtAndVTable());
+  SetFieldPtrWithSize<false>(EmbeddedImTableEntryOffset(i, pointer_size), method, pointer_size);
 }
 
 inline bool Class::HasVTable() {
-  return (GetVTable() != nullptr) || ShouldHaveEmbeddedImtAndVTable();
+  return GetVTable() != nullptr || ShouldHaveEmbeddedImtAndVTable();
 }
 
 inline int32_t Class::GetVTableLength() {
   if (ShouldHaveEmbeddedImtAndVTable()) {
     return GetEmbeddedVTableLength();
   }
-  return (GetVTable() != nullptr) ? GetVTable()->GetLength() : 0;
+  return GetVTable() != nullptr ? GetVTable()->GetLength() : 0;
 }
 
-inline ArtMethod* Class::GetVTableEntry(uint32_t i) {
+inline ArtMethod* Class::GetVTableEntry(uint32_t i, size_t pointer_size) {
   if (ShouldHaveEmbeddedImtAndVTable()) {
-    return GetEmbeddedVTableEntry(i);
+    return GetEmbeddedVTableEntry(i, pointer_size);
   }
-  return (GetVTable() != nullptr) ? GetVTable()->Get(i) : nullptr;
+  auto* vtable = GetVTable();
+  DCHECK(vtable != nullptr);
+  return vtable->GetElementPtrSize<ArtMethod*>(i, pointer_size);
 }
 
 inline int32_t Class::GetEmbeddedVTableLength() {
-  return GetField32(EmbeddedVTableLengthOffset());
+  return GetField32(MemberOffset(EmbeddedVTableLengthOffset()));
 }
 
 inline void Class::SetEmbeddedVTableLength(int32_t len) {
-  SetField32<false>(EmbeddedVTableLengthOffset(), len);
+  SetField32<false>(MemberOffset(EmbeddedVTableLengthOffset()), len);
 }
 
-inline ArtMethod* Class::GetEmbeddedVTableEntry(uint32_t i) {
-  uint32_t offset = EmbeddedVTableOffset().Uint32Value() + i * sizeof(VTableEntry);
-  return GetFieldObject<mirror::ArtMethod>(MemberOffset(offset));
+inline MemberOffset Class::EmbeddedVTableEntryOffset(uint32_t i, size_t pointer_size) {
+  return MemberOffset(
+      EmbeddedVTableOffset(pointer_size).Uint32Value() + i * VTableEntrySize(pointer_size));
 }
 
-inline void Class::SetEmbeddedVTableEntry(uint32_t i, ArtMethod* method) {
-  uint32_t offset = EmbeddedVTableOffset().Uint32Value() + i * sizeof(VTableEntry);
-  SetFieldObject<false>(MemberOffset(offset), method);
-  CHECK(method == GetVTableDuringLinking()->Get(i));
+inline ArtMethod* Class::GetEmbeddedVTableEntry(uint32_t i, size_t pointer_size) {
+  return GetFieldPtrWithSize<ArtMethod*>(EmbeddedVTableEntryOffset(i, pointer_size), pointer_size);
+}
+
+inline void Class::SetEmbeddedVTableEntryUnchecked(
+    uint32_t i, ArtMethod* method, size_t pointer_size) {
+  SetFieldPtrWithSize<false>(EmbeddedVTableEntryOffset(i, pointer_size), method, pointer_size);
+}
+
+inline void Class::SetEmbeddedVTableEntry(uint32_t i, ArtMethod* method, size_t pointer_size) {
+  auto* vtable = GetVTableDuringLinking();
+  CHECK_EQ(method, vtable->GetElementPtrSize<ArtMethod*>(i, pointer_size));
+  SetEmbeddedVTableEntryUnchecked(i, method, pointer_size);
 }
 
 inline bool Class::Implements(Class* klass) {
@@ -340,41 +368,43 @@
   return false;
 }
 
-inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method) {
+inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method, size_t pointer_size) {
   Class* declaring_class = method->GetDeclaringClass();
   DCHECK(declaring_class != nullptr) << PrettyClass(this);
   DCHECK(declaring_class->IsInterface()) << PrettyMethod(method);
   // TODO cache to improve lookup speed
-  int32_t iftable_count = GetIfTableCount();
+  const int32_t iftable_count = GetIfTableCount();
   IfTable* iftable = GetIfTable();
   for (int32_t i = 0; i < iftable_count; i++) {
     if (iftable->GetInterface(i) == declaring_class) {
-      return iftable->GetMethodArray(i)->Get(method->GetMethodIndex());
+      return iftable->GetMethodArray(i)->GetElementPtrSize<ArtMethod*>(
+          method->GetMethodIndex(), pointer_size);
     }
   }
   return nullptr;
 }
 
-inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method) {
+inline ArtMethod* Class::FindVirtualMethodForVirtual(ArtMethod* method, size_t pointer_size) {
   DCHECK(!method->GetDeclaringClass()->IsInterface() || method->IsMiranda());
   // The argument method may from a super class.
   // Use the index to a potentially overridden one for this instance's class.
-  return GetVTableEntry(method->GetMethodIndex());
+  return GetVTableEntry(method->GetMethodIndex(), pointer_size);
 }
 
-inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method) {
+inline ArtMethod* Class::FindVirtualMethodForSuper(ArtMethod* method, size_t pointer_size) {
   DCHECK(!method->GetDeclaringClass()->IsInterface());
-  return GetSuperClass()->GetVTableEntry(method->GetMethodIndex());
+  return GetSuperClass()->GetVTableEntry(method->GetMethodIndex(), pointer_size);
 }
 
-inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method) {
+inline ArtMethod* Class::FindVirtualMethodForVirtualOrInterface(ArtMethod* method,
+                                                                size_t pointer_size) {
   if (method->IsDirect()) {
     return method;
   }
   if (method->GetDeclaringClass()->IsInterface() && !method->IsMiranda()) {
-    return FindVirtualMethodForInterface(method);
+    return FindVirtualMethodForInterface(method, pointer_size);
   }
-  return FindVirtualMethodForVirtual(method);
+  return FindVirtualMethodForVirtual(method, pointer_size);
 }
 
 inline IfTable* Class::GetIfTable() {
@@ -406,24 +436,24 @@
       : ClassOffset();
 }
 
-inline MemberOffset Class::GetFirstReferenceStaticFieldOffset() {
+inline MemberOffset Class::GetFirstReferenceStaticFieldOffset(size_t pointer_size) {
   DCHECK(IsResolved());
   uint32_t base = sizeof(mirror::Class);  // Static fields come after the class.
   if (ShouldHaveEmbeddedImtAndVTable()) {
     // Static fields come after the embedded tables.
-    base = mirror::Class::ComputeClassSize(true, GetEmbeddedVTableLength(),
-                                           0, 0, 0, 0, 0);
+    base = mirror::Class::ComputeClassSize(
+        true, GetEmbeddedVTableLength(), 0, 0, 0, 0, 0, pointer_size);
   }
   return MemberOffset(base);
 }
 
-inline MemberOffset Class::GetFirstReferenceStaticFieldOffsetDuringLinking() {
+inline MemberOffset Class::GetFirstReferenceStaticFieldOffsetDuringLinking(size_t pointer_size) {
   DCHECK(IsLoaded());
   uint32_t base = sizeof(mirror::Class);  // Static fields come after the class.
   if (ShouldHaveEmbeddedImtAndVTable()) {
     // Static fields come after the embedded tables.
     base = mirror::Class::ComputeClassSize(true, GetVTableDuringLinking()->GetLength(),
-                                           0, 0, 0, 0, 0);
+                                           0, 0, 0, 0, 0, pointer_size);
   }
   return MemberOffset(base);
 }
@@ -499,14 +529,12 @@
   // circularity issue during loading the names of its members
   DCHECK(IsIdxLoaded<kVerifyFlags>() || IsRetired<kVerifyFlags>() ||
          IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ||
-         this == String::GetJavaLangString() ||
-         this == ArtMethod::GetJavaLangReflectArtMethod())
+         this == String::GetJavaLangString())
       << "IsIdxLoaded=" << IsIdxLoaded<kVerifyFlags>()
       << " IsRetired=" << IsRetired<kVerifyFlags>()
       << " IsErroneous=" <<
           IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>()
       << " IsString=" << (this == String::GetJavaLangString())
-      << " IsArtMethod=" << (this == ArtMethod::GetJavaLangReflectArtMethod())
       << " descriptor=" << PrettyDescriptor(this);
   return GetField32<kVerifyFlags>(AccessFlagsOffset());
 }
@@ -594,20 +622,20 @@
                                         uint32_t num_16bit_static_fields,
                                         uint32_t num_32bit_static_fields,
                                         uint32_t num_64bit_static_fields,
-                                        uint32_t num_ref_static_fields) {
+                                        uint32_t num_ref_static_fields,
+                                        size_t pointer_size) {
   // Space used by java.lang.Class and its instance fields.
   uint32_t size = sizeof(Class);
   // Space used by embedded tables.
   if (has_embedded_tables) {
-    uint32_t embedded_imt_size = kImtSize * sizeof(ImTableEntry);
-    uint32_t embedded_vtable_size = num_vtable_entries * sizeof(VTableEntry);
-    size += embedded_imt_size +
-            sizeof(int32_t) /* vtable len */ +
-            embedded_vtable_size;
+    const uint32_t embedded_imt_size = kImtSize * ImTableEntrySize(pointer_size);
+    const uint32_t embedded_vtable_size = num_vtable_entries * VTableEntrySize(pointer_size);
+    size = RoundUp(size + sizeof(uint32_t) /* embedded vtable len */, pointer_size) +
+        embedded_imt_size + embedded_vtable_size;
   }
 
   // Space used by reference statics.
-  size +=  num_ref_static_fields * sizeof(HeapReference<Object>);
+  size += num_ref_static_fields * sizeof(HeapReference<Object>);
   if (!IsAligned<8>(size) && num_64bit_static_fields > 0) {
     uint32_t gap = 8 - (size & 0x7);
     size += gap;  // will be padded
@@ -629,10 +657,8 @@
   }
   // Guaranteed to be at least 4 byte aligned. No need for further alignments.
   // Space used for primitive static fields.
-  size += (num_8bit_static_fields * sizeof(uint8_t)) +
-      (num_16bit_static_fields * sizeof(uint16_t)) +
-      (num_32bit_static_fields * sizeof(uint32_t)) +
-      (num_64bit_static_fields * sizeof(uint64_t));
+  size += num_8bit_static_fields * sizeof(uint8_t) + num_16bit_static_fields * sizeof(uint16_t) +
+      num_32bit_static_fields * sizeof(uint32_t) + num_64bit_static_fields * sizeof(uint64_t);
   return size;
 }
 
@@ -651,39 +677,9 @@
     // allocated with the right size for those. Also, unresolved classes don't have fields
     // linked yet.
     VisitStaticFieldsReferences<kVisitClass>(this, visitor);
-    if (ShouldHaveEmbeddedImtAndVTable()) {
-      VisitEmbeddedImtAndVTable(visitor);
-    }
   }
 }
 
-template<typename Visitor>
-inline void Class::VisitEmbeddedImtAndVTable(const Visitor& visitor) {
-  uint32_t pos = sizeof(mirror::Class);
-
-  size_t count = kImtSize;
-  for (size_t i = 0; i < count; ++i) {
-    MemberOffset offset = MemberOffset(pos);
-    visitor(this, offset, true);
-    pos += sizeof(ImTableEntry);
-  }
-
-  // Skip vtable length.
-  pos += sizeof(int32_t);
-
-  count = GetEmbeddedVTableLength();
-  for (size_t i = 0; i < count; ++i) {
-    MemberOffset offset = MemberOffset(pos);
-    visitor(this, offset, true);
-    pos += sizeof(VTableEntry);
-  }
-}
-
-template<ReadBarrierOption kReadBarrierOption>
-inline bool Class::IsArtMethodClass() const {
-  return this == ArtMethod::GetJavaLangReflectArtMethod<kReadBarrierOption>();
-}
-
 template<ReadBarrierOption kReadBarrierOption>
 inline bool Class::IsReferenceClass() const {
   return this == Reference::GetJavaLangRefReference<kReadBarrierOption>();
@@ -812,27 +808,92 @@
 }
 
 template<class Visitor>
-void mirror::Class::VisitFieldRoots(Visitor& visitor) {
+void mirror::Class::VisitNativeRoots(Visitor& visitor, size_t pointer_size) {
   ArtField* const sfields = GetSFieldsUnchecked();
   // Since we visit class roots while we may be writing these fields, check against null.
-  // TODO: Is this safe for concurrent compaction?
   if (sfields != nullptr) {
     for (size_t i = 0, count = NumStaticFields(); i < count; ++i) {
+      auto* f = &sfields[i];
       if (kIsDebugBuild && IsResolved()) {
-        CHECK_EQ(sfields[i].GetDeclaringClass(), this) << GetStatus();
+        CHECK_EQ(f->GetDeclaringClass(), this) << GetStatus();
       }
-      visitor.VisitRoot(sfields[i].DeclaringClassRoot().AddressWithoutBarrier());
+      f->VisitRoots(visitor);
     }
   }
   ArtField* const ifields = GetIFieldsUnchecked();
   if (ifields != nullptr) {
     for (size_t i = 0, count = NumInstanceFields(); i < count; ++i) {
+      auto* f = &ifields[i];
       if (kIsDebugBuild && IsResolved()) {
-        CHECK_EQ(ifields[i].GetDeclaringClass(), this) << GetStatus();
+        CHECK_EQ(f->GetDeclaringClass(), this) << GetStatus();
       }
-      visitor.VisitRoot(ifields[i].DeclaringClassRoot().AddressWithoutBarrier());
+      f->VisitRoots(visitor);
     }
   }
+  for (auto& m : GetDirectMethods(pointer_size)) {
+    m.VisitRoots(visitor);
+  }
+  for (auto& m : GetVirtualMethods(pointer_size)) {
+    m.VisitRoots(visitor);
+  }
+}
+
+inline StrideIterator<ArtMethod> Class::DirectMethodsBegin(size_t pointer_size)  {
+  CheckPointerSize(pointer_size);
+  auto* methods = GetDirectMethodsPtrUnchecked();
+  auto stride = ArtMethod::ObjectSize(pointer_size);
+  return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods), stride);
+}
+
+inline StrideIterator<ArtMethod> Class::DirectMethodsEnd(size_t pointer_size) {
+  CheckPointerSize(pointer_size);
+  auto* methods = GetDirectMethodsPtrUnchecked();
+  auto stride = ArtMethod::ObjectSize(pointer_size);
+  auto count = NumDirectMethods();
+  return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods) + stride * count, stride);
+}
+
+inline IterationRange<StrideIterator<ArtMethod>> Class::GetDirectMethods(size_t pointer_size) {
+  CheckPointerSize(pointer_size);
+  return MakeIterationRange(DirectMethodsBegin(pointer_size), DirectMethodsEnd(pointer_size));
+}
+
+inline StrideIterator<ArtMethod> Class::VirtualMethodsBegin(size_t pointer_size)  {
+  CheckPointerSize(pointer_size);
+  auto* methods = GetVirtualMethodsPtrUnchecked();
+  auto stride = ArtMethod::ObjectSize(pointer_size);
+  return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods), stride);
+}
+
+inline StrideIterator<ArtMethod> Class::VirtualMethodsEnd(size_t pointer_size) {
+  CheckPointerSize(pointer_size);
+  auto* methods = GetVirtualMethodsPtrUnchecked();
+  auto stride = ArtMethod::ObjectSize(pointer_size);
+  auto count = NumVirtualMethods();
+  return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods) + stride * count, stride);
+}
+
+inline IterationRange<StrideIterator<ArtMethod>> Class::GetVirtualMethods(size_t pointer_size) {
+  return MakeIterationRange(VirtualMethodsBegin(pointer_size), VirtualMethodsEnd(pointer_size));
+}
+
+inline MemberOffset Class::EmbeddedImTableOffset(size_t pointer_size) {
+  CheckPointerSize(pointer_size);
+  // Round up since we want the embedded imt and vtable to be pointer size aligned in case 64 bits.
+  // Add 32 bits for embedded vtable length.
+  return MemberOffset(
+      RoundUp(EmbeddedVTableLengthOffset().Uint32Value() + sizeof(uint32_t), pointer_size));
+}
+
+inline MemberOffset Class::EmbeddedVTableOffset(size_t pointer_size) {
+  CheckPointerSize(pointer_size);
+  return MemberOffset(EmbeddedImTableOffset(pointer_size).Uint32Value() +
+                      kImtSize * ImTableEntrySize(pointer_size));
+}
+
+inline void Class::CheckPointerSize(size_t pointer_size) {
+  DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
+  DCHECK_EQ(pointer_size, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
 }
 
 }  // namespace mirror
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 56c586a..482640b 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -145,9 +145,10 @@
 }
 
 void Class::SetClassSize(uint32_t new_class_size) {
-  if (kIsDebugBuild && (new_class_size < GetClassSize())) {
-    DumpClass(LOG(ERROR), kDumpClassFullDetail);
-    CHECK_GE(new_class_size, GetClassSize()) << " class=" << PrettyTypeOf(this);
+  if (kIsDebugBuild && new_class_size < GetClassSize()) {
+    DumpClass(LOG(INTERNAL_FATAL), kDumpClassFullDetail);
+    LOG(INTERNAL_FATAL) << new_class_size << " vs " << GetClassSize();
+    LOG(FATAL) << " class=" << PrettyTypeOf(this);
   }
   // Not called within a transaction.
   SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size);
@@ -205,10 +206,11 @@
     return;
   }
 
-  Thread* self = Thread::Current();
+  Thread* const self = Thread::Current();
   StackHandleScope<2> hs(self);
   Handle<mirror::Class> h_this(hs.NewHandle(this));
   Handle<mirror::Class> h_super(hs.NewHandle(GetSuperClass()));
+  auto image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
 
   std::string temp;
   os << "----- " << (IsInterface() ? "interface" : "class") << " "
@@ -244,12 +246,13 @@
     os << "  vtable (" << h_this->NumVirtualMethods() << " entries, "
         << (h_super.Get() != nullptr ? h_super->NumVirtualMethods() : 0) << " in super):\n";
     for (size_t i = 0; i < NumVirtualMethods(); ++i) {
-      os << StringPrintf("    %2zd: %s\n", i,
-                         PrettyMethod(h_this->GetVirtualMethodDuringLinking(i)).c_str());
+      os << StringPrintf("    %2zd: %s\n", i, PrettyMethod(
+          h_this->GetVirtualMethodDuringLinking(i, image_pointer_size)).c_str());
     }
     os << "  direct methods (" << h_this->NumDirectMethods() << " entries):\n";
     for (size_t i = 0; i < h_this->NumDirectMethods(); ++i) {
-      os << StringPrintf("    %2zd: %s\n", i, PrettyMethod(h_this->GetDirectMethod(i)).c_str());
+      os << StringPrintf("    %2zd: %s\n", i, PrettyMethod(
+          h_this->GetDirectMethod(i, image_pointer_size)).c_str());
     }
     if (h_this->NumStaticFields() > 0) {
       os << "  static fields (" << h_this->NumStaticFields() << " entries):\n";
@@ -275,7 +278,7 @@
 }
 
 void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
-  if (kIsDebugBuild && (new_reference_offsets != kClassWalkSuper)) {
+  if (kIsDebugBuild && new_reference_offsets != kClassWalkSuper) {
     // Sanity check that the number of bits set in the reference offset bitmap
     // agrees with the number of references
     uint32_t count = 0;
@@ -342,9 +345,10 @@
   }
 }
 
-ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const StringPiece& signature) {
+ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const StringPiece& signature,
+                                      size_t pointer_size) {
   // Check the current class before checking the interfaces.
-  ArtMethod* method = FindDeclaredVirtualMethod(name, signature);
+  ArtMethod* method = FindDeclaredVirtualMethod(name, signature, pointer_size);
   if (method != nullptr) {
     return method;
   }
@@ -352,7 +356,7 @@
   int32_t iftable_count = GetIfTableCount();
   IfTable* iftable = GetIfTable();
   for (int32_t i = 0; i < iftable_count; ++i) {
-    method = iftable->GetInterface(i)->FindDeclaredVirtualMethod(name, signature);
+    method = iftable->GetInterface(i)->FindDeclaredVirtualMethod(name, signature, pointer_size);
     if (method != nullptr) {
       return method;
     }
@@ -360,9 +364,10 @@
   return nullptr;
 }
 
-ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const Signature& signature) {
+ArtMethod* Class::FindInterfaceMethod(const StringPiece& name, const Signature& signature,
+                                      size_t pointer_size) {
   // Check the current class before checking the interfaces.
-  ArtMethod* method = FindDeclaredVirtualMethod(name, signature);
+  ArtMethod* method = FindDeclaredVirtualMethod(name, signature, pointer_size);
   if (method != nullptr) {
     return method;
   }
@@ -370,7 +375,7 @@
   int32_t iftable_count = GetIfTableCount();
   IfTable* iftable = GetIfTable();
   for (int32_t i = 0; i < iftable_count; ++i) {
-    method = iftable->GetInterface(i)->FindDeclaredVirtualMethod(name, signature);
+    method = iftable->GetInterface(i)->FindDeclaredVirtualMethod(name, signature, pointer_size);
     if (method != nullptr) {
       return method;
     }
@@ -378,9 +383,10 @@
   return nullptr;
 }
 
-ArtMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
+ArtMethod* Class::FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx,
+                                      size_t pointer_size) {
   // Check the current class before checking the interfaces.
-  ArtMethod* method = FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
+  ArtMethod* method = FindDeclaredVirtualMethod(dex_cache, dex_method_idx, pointer_size);
   if (method != nullptr) {
     return method;
   }
@@ -388,7 +394,8 @@
   int32_t iftable_count = GetIfTableCount();
   IfTable* iftable = GetIfTable();
   for (int32_t i = 0; i < iftable_count; ++i) {
-    method = iftable->GetInterface(i)->FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
+    method = iftable->GetInterface(i)->FindDeclaredVirtualMethod(
+        dex_cache, dex_method_idx, pointer_size);
     if (method != nullptr) {
       return method;
     }
@@ -396,41 +403,42 @@
   return nullptr;
 }
 
-ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) {
-  for (size_t i = 0; i < NumDirectMethods(); ++i) {
-    ArtMethod* method = GetDirectMethod(i);
-    if (name == method->GetName() && method->GetSignature() == signature) {
-      return method;
+ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature,
+                                           size_t pointer_size) {
+  for (auto& method : GetDirectMethods(pointer_size)) {
+    if (name == method.GetName() && method.GetSignature() == signature) {
+      return &method;
     }
   }
   return nullptr;
 }
 
-ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature) {
-  for (size_t i = 0; i < NumDirectMethods(); ++i) {
-    ArtMethod* method = GetDirectMethod(i);
-    if (name == method->GetName() && signature == method->GetSignature()) {
-      return method;
+ArtMethod* Class::FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature,
+                                           size_t pointer_size) {
+  for (auto& method : GetDirectMethods(pointer_size)) {
+    if (name == method.GetName() && signature == method.GetSignature()) {
+      return &method;
     }
   }
   return nullptr;
 }
 
-ArtMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
+ArtMethod* Class::FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx,
+                                           size_t pointer_size) {
   if (GetDexCache() == dex_cache) {
-    for (size_t i = 0; i < NumDirectMethods(); ++i) {
-      ArtMethod* method = GetDirectMethod(i);
-      if (method->GetDexMethodIndex() == dex_method_idx) {
-        return method;
+    for (auto& method : GetDirectMethods(pointer_size)) {
+      if (method.GetDexMethodIndex() == dex_method_idx) {
+        return &method;
       }
     }
   }
   return nullptr;
 }
 
-ArtMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& signature) {
+ArtMethod* Class::FindDirectMethod(const StringPiece& name, const StringPiece& signature,
+                                   size_t pointer_size) {
   for (Class* klass = this; klass != nullptr; klass = klass->GetSuperClass()) {
-    ArtMethod* method = klass->FindDeclaredDirectMethod(name, signature);
+    ArtMethod* method = klass->FindDeclaredDirectMethod(name, signature, pointer_size);
     if (method != nullptr) {
       return method;
     }
@@ -438,9 +446,10 @@
   return nullptr;
 }
 
-ArtMethod* Class::FindDirectMethod(const StringPiece& name, const Signature& signature) {
+ArtMethod* Class::FindDirectMethod(const StringPiece& name, const Signature& signature,
+                                   size_t pointer_size) {
   for (Class* klass = this; klass != nullptr; klass = klass->GetSuperClass()) {
-    ArtMethod* method = klass->FindDeclaredDirectMethod(name, signature);
+    ArtMethod* method = klass->FindDeclaredDirectMethod(name, signature, pointer_size);
     if (method != nullptr) {
       return method;
     }
@@ -448,9 +457,10 @@
   return nullptr;
 }
 
-ArtMethod* Class::FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
+ArtMethod* Class::FindDirectMethod(
+    const DexCache* dex_cache, uint32_t dex_method_idx, size_t pointer_size) {
   for (Class* klass = this; klass != nullptr; klass = klass->GetSuperClass()) {
-    ArtMethod* method = klass->FindDeclaredDirectMethod(dex_cache, dex_method_idx);
+    ArtMethod* method = klass->FindDeclaredDirectMethod(dex_cache, dex_method_idx, pointer_size);
     if (method != nullptr) {
       return method;
     }
@@ -458,44 +468,44 @@
   return nullptr;
 }
 
-ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) {
-  for (size_t i = 0; i < NumVirtualMethods(); ++i) {
-    ArtMethod* method = GetVirtualMethod(i);
-    if (name == method->GetName() && method->GetSignature() == signature) {
-      return method;
+ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature,
+                                            size_t pointer_size) {
+  for (auto& method : GetVirtualMethods(pointer_size)) {
+    if (name == method.GetName() && method.GetSignature() == signature) {
+      return &method;
     }
   }
   return nullptr;
 }
 
-ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature) {
-  for (size_t i = 0; i < NumVirtualMethods(); ++i) {
-    ArtMethod* method = GetVirtualMethod(i);
-    if (name == method->GetName() && signature == method->GetSignature()) {
-      return method;
+ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature,
+                                            size_t pointer_size) {
+  for (auto& method : GetVirtualMethods(pointer_size)) {
+    if (name == method.GetName() && signature == method.GetSignature()) {
+      return &method;
     }
   }
   return nullptr;
 }
 
-ArtMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
+ArtMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx,
+                                            size_t pointer_size) {
   if (GetDexCache() == dex_cache) {
-    for (size_t i = 0; i < NumVirtualMethods(); ++i) {
-      ArtMethod* method = GetVirtualMethod(i);
-      if (method->GetDexMethodIndex() == dex_method_idx &&
-          // A miranda method may have a different DexCache and is always created by linking,
-          // never *declared* in the class.
-          !method->IsMiranda()) {
-        return method;
+    for (auto& method : GetVirtualMethods(pointer_size)) {
+      // A miranda method may have a different DexCache and is always created by linking,
+      // never *declared* in the class.
+      if (method.GetDexMethodIndex() == dex_method_idx && !method.IsMiranda()) {
+        return &method;
       }
     }
   }
   return nullptr;
 }
 
-ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const StringPiece& signature) {
+ArtMethod* Class::FindVirtualMethod(
+    const StringPiece& name, const StringPiece& signature, size_t pointer_size) {
   for (Class* klass = this; klass != nullptr; klass = klass->GetSuperClass()) {
-    ArtMethod* method = klass->FindDeclaredVirtualMethod(name, signature);
+    ArtMethod* method = klass->FindDeclaredVirtualMethod(name, signature, pointer_size);
     if (method != nullptr) {
       return method;
     }
@@ -503,9 +513,10 @@
   return nullptr;
 }
 
-ArtMethod* Class::FindVirtualMethod(const StringPiece& name, const Signature& signature) {
+ArtMethod* Class::FindVirtualMethod(
+    const StringPiece& name, const Signature& signature, size_t pointer_size) {
   for (Class* klass = this; klass != nullptr; klass = klass->GetSuperClass()) {
-    ArtMethod* method = klass->FindDeclaredVirtualMethod(name, signature);
+    ArtMethod* method = klass->FindDeclaredVirtualMethod(name, signature, pointer_size);
     if (method != nullptr) {
       return method;
     }
@@ -513,9 +524,10 @@
   return nullptr;
 }
 
-ArtMethod* Class::FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) {
+ArtMethod* Class::FindVirtualMethod(
+    const DexCache* dex_cache, uint32_t dex_method_idx, size_t pointer_size) {
   for (Class* klass = this; klass != nullptr; klass = klass->GetSuperClass()) {
-    ArtMethod* method = klass->FindDeclaredVirtualMethod(dex_cache, dex_method_idx);
+    ArtMethod* method = klass->FindDeclaredVirtualMethod(dex_cache, dex_method_idx, pointer_size);
     if (method != nullptr) {
       return method;
     }
@@ -523,13 +535,12 @@
   return nullptr;
 }
 
-ArtMethod* Class::FindClassInitializer() {
-  for (size_t i = 0; i < NumDirectMethods(); ++i) {
-    ArtMethod* method = GetDirectMethod(i);
-    if (method->IsClassInitializer()) {
-      DCHECK_STREQ(method->GetName(), "<clinit>");
-      DCHECK_STREQ(method->GetSignature().ToString().c_str(), "()V");
-      return method;
+ArtMethod* Class::FindClassInitializer(size_t pointer_size) {
+  for (ArtMethod& method : GetDirectMethods(pointer_size)) {
+    if (method.IsClassInitializer()) {
+      DCHECK_STREQ(method.GetName(), "<clinit>");
+      DCHECK_STREQ(method.GetSignature().ToString().c_str(), "()V");
+      return &method;
     }
   }
   return nullptr;
@@ -684,23 +695,18 @@
   return nullptr;
 }
 
-static void SetPreverifiedFlagOnMethods(mirror::ObjectArray<mirror::ArtMethod>* methods)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  if (methods != nullptr) {
-    for (int32_t index = 0, end = methods->GetLength(); index < end; ++index) {
-      mirror::ArtMethod* method = methods->GetWithoutChecks(index);
-      DCHECK(method != nullptr);
-      if (!method->IsNative() && !method->IsAbstract()) {
-        method->SetPreverified();
-      }
+void Class::SetPreverifiedFlagOnAllMethods(size_t pointer_size) {
+  DCHECK(IsVerified());
+  for (auto& m : GetDirectMethods(pointer_size)) {
+    if (!m.IsNative() && !m.IsAbstract()) {
+      m.SetPreverified();
     }
   }
-}
-
-void Class::SetPreverifiedFlagOnAllMethods() {
-  DCHECK(IsVerified());
-  SetPreverifiedFlagOnMethods(GetDirectMethods());
-  SetPreverifiedFlagOnMethods(GetVirtualMethods());
+  for (auto& m : GetVirtualMethods(pointer_size)) {
+    if (!m.IsNative() && !m.IsAbstract()) {
+      m.SetPreverified();
+    }
+  }
 }
 
 const char* Class::GetDescriptor(std::string* storage) {
@@ -795,21 +801,20 @@
   return GetDexFile().GetInterfacesList(*class_def);
 }
 
-void Class::PopulateEmbeddedImtAndVTable(StackHandleScope<kImtSize>* imt_handle_scope) {
-  for (uint32_t i = 0; i < kImtSize; i++) {
-    // Replace null with conflict.
-    mirror::Object* obj = imt_handle_scope->GetReference(i);
-    DCHECK(obj != nullptr);
-    SetEmbeddedImTableEntry(i, obj->AsArtMethod());
+void Class::PopulateEmbeddedImtAndVTable(ArtMethod* const (&methods)[kImtSize],
+                                         size_t pointer_size) {
+  for (size_t i = 0; i < kImtSize; i++) {
+    auto method = methods[i];
+    DCHECK(method != nullptr);
+    SetEmbeddedImTableEntry(i, Runtime::Current()->GetImtConflictMethod(), pointer_size);
   }
-
-  ObjectArray<ArtMethod>* table = GetVTableDuringLinking();
+  PointerArray* table = GetVTableDuringLinking();
   CHECK(table != nullptr) << PrettyClass(this);
-  SetEmbeddedVTableLength(table->GetLength());
-  for (int32_t i = 0; i < table->GetLength(); i++) {
-    SetEmbeddedVTableEntry(i, table->GetWithoutChecks(i));
+  const size_t table_length = table->GetLength();
+  SetEmbeddedVTableLength(table_length);
+  for (size_t i = 0; i < table_length; i++) {
+    SetEmbeddedVTableEntry(i, table->GetElementPtrSize<ArtMethod*>(i, pointer_size), pointer_size);
   }
-
   // Keep java.lang.Object class's vtable around for since it's easier
   // to be reused by array classes during their linking.
   if (!IsObjectClass()) {
@@ -820,21 +825,20 @@
 // The pre-fence visitor for Class::CopyOf().
 class CopyClassVisitor {
  public:
-  explicit CopyClassVisitor(Thread* self, Handle<mirror::Class>* orig,
-                            size_t new_length, size_t copy_bytes,
-                            StackHandleScope<mirror::Class::kImtSize>* imt_handle_scope)
+  explicit CopyClassVisitor(Thread* self, Handle<mirror::Class>* orig, size_t new_length,
+                            size_t copy_bytes, ArtMethod* const (&imt)[mirror::Class::kImtSize],
+                            size_t pointer_size)
       : self_(self), orig_(orig), new_length_(new_length),
-        copy_bytes_(copy_bytes), imt_handle_scope_(imt_handle_scope) {
+        copy_bytes_(copy_bytes), imt_(imt), pointer_size_(pointer_size) {
   }
 
-  void operator()(Object* obj, size_t usable_size) const
+  void operator()(mirror::Object* obj, size_t usable_size ATTRIBUTE_UNUSED) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    UNUSED(usable_size);
     StackHandleScope<1> hs(self_);
     Handle<mirror::Class> h_new_class_obj(hs.NewHandle(obj->AsClass()));
     mirror::Object::CopyObject(self_, h_new_class_obj.Get(), orig_->Get(), copy_bytes_);
     mirror::Class::SetStatus(h_new_class_obj, Class::kStatusResolving, self_);
-    h_new_class_obj->PopulateEmbeddedImtAndVTable(imt_handle_scope_);
+    h_new_class_obj->PopulateEmbeddedImtAndVTable(imt_, pointer_size_);
     h_new_class_obj->SetClassSize(new_length_);
   }
 
@@ -843,12 +847,13 @@
   Handle<mirror::Class>* const orig_;
   const size_t new_length_;
   const size_t copy_bytes_;
-  StackHandleScope<mirror::Class::kImtSize>* const imt_handle_scope_;
+  ArtMethod* const (&imt_)[mirror::Class::kImtSize];
+  const size_t pointer_size_;
   DISALLOW_COPY_AND_ASSIGN(CopyClassVisitor);
 };
 
 Class* Class::CopyOf(Thread* self, int32_t new_length,
-                     StackHandleScope<kImtSize>* imt_handle_scope) {
+                     ArtMethod* const (&imt)[mirror::Class::kImtSize], size_t pointer_size) {
   DCHECK_GE(new_length, static_cast<int32_t>(sizeof(Class)));
   // We may get copied by a compacting GC.
   StackHandleScope<1> hs(self);
@@ -856,13 +861,12 @@
   gc::Heap* heap = Runtime::Current()->GetHeap();
   // The num_bytes (3rd param) is sizeof(Class) as opposed to SizeOf()
   // to skip copying the tail part that we will overwrite here.
-  CopyClassVisitor visitor(self, &h_this, new_length, sizeof(Class), imt_handle_scope);
-  mirror::Object* new_class =
-      kMovingClasses
-         ? heap->AllocObject<true>(self, java_lang_Class_.Read(), new_length, visitor)
-         : heap->AllocNonMovableObject<true>(self, java_lang_Class_.Read(), new_length, visitor);
+  CopyClassVisitor visitor(self, &h_this, new_length, sizeof(Class), imt, pointer_size);
+  mirror::Object* new_class = kMovingClasses ?
+      heap->AllocObject<true>(self, java_lang_Class_.Read(), new_length, visitor) :
+      heap->AllocNonMovableObject<true>(self, java_lang_Class_.Read(), new_length, visitor);
   if (UNLIKELY(new_class == nullptr)) {
-    CHECK(self->IsExceptionPending());  // Expect an OOME.
+    self->AssertPendingOOMException();
     return nullptr;
   }
   return new_class->AsClass();
@@ -873,26 +877,32 @@
   return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match;
 }
 
-mirror::ArtMethod* Class::GetDeclaredConstructor(
+// TODO: Move this to java_lang_Class.cc?
+ArtMethod* Class::GetDeclaredConstructor(
     Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args) {
-  auto* direct_methods = GetDirectMethods();
-  size_t count = direct_methods != nullptr ? direct_methods->GetLength() : 0u;
-  for (size_t i = 0; i < count; ++i) {
-    auto* m = direct_methods->GetWithoutChecks(i);
+  for (auto& m : GetDirectMethods(sizeof(void*))) {
     // Skip <clinit> which is a static constructor, as well as non constructors.
-    if (m->IsStatic() || !m->IsConstructor()) {
+    if (m.IsStatic() || !m.IsConstructor()) {
       continue;
     }
     // May cause thread suspension and exceptions.
-    if (m->EqualParameters(args)) {
-      return m;
+    if (m.GetInterfaceMethodIfProxy(sizeof(void*))->EqualParameters(args)) {
+      return &m;
     }
-    if (self->IsExceptionPending()) {
+    if (UNLIKELY(self->IsExceptionPending())) {
       return nullptr;
     }
   }
   return nullptr;
 }
 
+uint32_t Class::Depth() {
+  uint32_t depth = 0;
+  for (Class* klass = this; klass->GetSuperClass() != nullptr; klass = klass->GetSuperClass()) {
+    depth++;
+  }
+  return depth;
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index b99fc68..ba8a693 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_MIRROR_CLASS_H_
 #define ART_RUNTIME_MIRROR_CLASS_H_
 
+#include "base/iteration_range.h"
 #include "dex_file.h"
 #include "gc_root.h"
 #include "gc/allocator_type.h"
@@ -27,6 +28,8 @@
 #include "object_callbacks.h"
 #include "primitive.h"
 #include "read_barrier_option.h"
+#include "stride_iterator.h"
+#include "utils.h"
 
 #ifndef IMT_SIZE
 #error IMT_SIZE not defined
@@ -35,6 +38,7 @@
 namespace art {
 
 class ArtField;
+class ArtMethod;
 struct ClassOffsets;
 template<class T> class Handle;
 template<class T> class Handle;
@@ -44,7 +48,6 @@
 
 namespace mirror {
 
-class ArtMethod;
 class ClassLoader;
 class Constructor;
 class DexCache;
@@ -64,16 +67,6 @@
   // (non-marker) interfaces.
   static constexpr size_t kImtSize = IMT_SIZE;
 
-  // imtable entry embedded in class object.
-  struct MANAGED ImTableEntry {
-    HeapReference<ArtMethod> method;
-  };
-
-  // vtable entry embedded in class object.
-  struct MANAGED VTableEntry {
-    HeapReference<ArtMethod> method;
-  };
-
   // Class Status
   //
   // kStatusRetired: Class that's temporarily used till class linking time
@@ -406,13 +399,7 @@
   }
 
   // Depth of class from java.lang.Object
-  uint32_t Depth() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    uint32_t depth = 0;
-    for (Class* klass = this; klass->GetSuperClass() != nullptr; klass = klass->GetSuperClass()) {
-      depth++;
-    }
-    return depth;
-  }
+  uint32_t Depth() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
@@ -427,9 +414,6 @@
   bool IsThrowableClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  bool IsArtMethodClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
   bool IsReferenceClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static MemberOffset ComponentTypeOffset() {
@@ -469,12 +453,27 @@
 
   bool IsInstantiable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return (!IsPrimitive() && !IsInterface() && !IsAbstract()) ||
-        ((IsAbstract()) && IsArrayClass());
+        (IsAbstract() && IsArrayClass());
   }
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsObjectArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetComponentType<kVerifyFlags>() != nullptr && !GetComponentType<kVerifyFlags>()->IsPrimitive();
+    return GetComponentType<kVerifyFlags>() != nullptr &&
+        !GetComponentType<kVerifyFlags>()->IsPrimitive();
+  }
+
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  bool IsIntArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+    auto* component_type = GetComponentType<kVerifyFlags>();
+    return component_type != nullptr && component_type->template IsPrimitiveInt<kNewFlags>();
+  }
+
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  bool IsLongArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+    auto* component_type = GetComponentType<kVerifyFlags>();
+    return component_type != nullptr && component_type->template IsPrimitiveLong<kNewFlags>();
   }
 
   // Creates a raw object instance but does not invoke the default constructor.
@@ -517,18 +516,19 @@
                                    uint32_t num_16bit_static_fields,
                                    uint32_t num_32bit_static_fields,
                                    uint32_t num_64bit_static_fields,
-                                   uint32_t num_ref_static_fields);
+                                   uint32_t num_ref_static_fields,
+                                   size_t pointer_size);
 
   // The size of java.lang.Class.class.
-  static uint32_t ClassClassSize() {
+  static uint32_t ClassClassSize(size_t pointer_size) {
     // The number of vtable entries in java.lang.Class.
-    uint32_t vtable_entries = Object::kVTableLength + 66;
-    return ComputeClassSize(true, vtable_entries, 0, 0, 0, 1, 0);
+    uint32_t vtable_entries = Object::kVTableLength + 65;
+    return ComputeClassSize(true, vtable_entries, 0, 0, 0, 1, 0, pointer_size);
   }
 
   // The size of a java.lang.Class representing a primitive such as int.class.
-  static uint32_t PrimitiveClassSize() {
-    return ComputeClassSize(false, 0, 0, 0, 0, 0, 0);
+  static uint32_t PrimitiveClassSize(size_t pointer_size) {
+    return ComputeClassSize(false, 0, 0, 0, 0, 0, 0, pointer_size);
   }
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
@@ -673,60 +673,82 @@
   // Also updates the dex_cache_strings_ variable from new_dex_cache.
   void SetDexCache(DexCache* new_dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE ObjectArray<ArtMethod>* GetDirectMethods()
+  ALWAYS_INLINE StrideIterator<ArtMethod> DirectMethodsBegin(size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetDirectMethods(ObjectArray<ArtMethod>* new_direct_methods)
+  ALWAYS_INLINE StrideIterator<ArtMethod> DirectMethodsEnd(size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE ArtMethod* GetDirectMethod(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  void SetDirectMethod(uint32_t i, ArtMethod* f)  // TODO: uint16_t
+  ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetDirectMethods(size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  ArtMethod* GetDirectMethodsPtr() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);\
+
+  void SetDirectMethodsPtr(ArtMethod* new_direct_methods)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  // Used by image writer.
+  void SetDirectMethodsPtrUnchecked(ArtMethod* new_direct_methods)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  ALWAYS_INLINE ArtMethod* GetDirectMethod(size_t i, size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Use only when we are allocating populating the method arrays.
+  ALWAYS_INLINE ArtMethod* GetDirectMethodUnchecked(size_t i, size_t pointer_size)
+        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE ArtMethod* GetVirtualMethodUnchecked(size_t i, size_t pointer_size)
+        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // Returns the number of static, private, and constructor methods.
-  uint32_t NumDirectMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE uint32_t NumDirectMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_direct_methods_));
+  }
+  void SetNumDirectMethods(uint32_t num) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_direct_methods_), num);
+  }
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ALWAYS_INLINE ObjectArray<ArtMethod>* GetVirtualMethods()
+  ALWAYS_INLINE ArtMethod* GetVirtualMethodsPtr() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  ALWAYS_INLINE StrideIterator<ArtMethod> VirtualMethodsBegin(size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE void SetVirtualMethods(ObjectArray<ArtMethod>* new_virtual_methods)
+  ALWAYS_INLINE StrideIterator<ArtMethod> VirtualMethodsEnd(size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetVirtualMethods(size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void SetVirtualMethodsPtr(ArtMethod* new_virtual_methods)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns the number of non-inherited virtual methods.
-  ALWAYS_INLINE uint32_t NumVirtualMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE uint32_t NumVirtualMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_virtual_methods_));
+  }
+  void SetNumVirtualMethods(uint32_t num) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_virtual_methods_), num);
+  }
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ArtMethod* GetVirtualMethod(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  ArtMethod* GetVirtualMethodDuringLinking(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  void SetVirtualMethod(uint32_t i, ArtMethod* f)  // TODO: uint16_t
+  ArtMethod* GetVirtualMethod(size_t i, size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ALWAYS_INLINE ObjectArray<ArtMethod>* GetVTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  ALWAYS_INLINE ObjectArray<ArtMethod>* GetVTableDuringLinking()
+  ArtMethod* GetVirtualMethodDuringLinking(size_t i, size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetVTable(ObjectArray<ArtMethod>* new_vtable)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE PointerArray* GetVTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  ALWAYS_INLINE PointerArray* GetVTableDuringLinking() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void SetVTable(PointerArray* new_vtable) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static MemberOffset VTableOffset() {
     return OFFSET_OF_OBJECT_MEMBER(Class, vtable_);
   }
 
-  static MemberOffset EmbeddedImTableOffset() {
-    return MemberOffset(sizeof(Class));
-  }
-
   static MemberOffset EmbeddedVTableLengthOffset() {
-    return MemberOffset(sizeof(Class) + kImtSize * sizeof(mirror::Class::ImTableEntry));
-  }
-
-  static MemberOffset EmbeddedVTableOffset() {
-    return MemberOffset(sizeof(Class) + kImtSize * sizeof(ImTableEntry) + sizeof(int32_t));
+    return MemberOffset(sizeof(Class));
   }
 
   bool ShouldHaveEmbeddedImtAndVTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -735,90 +757,117 @@
 
   bool HasVTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* GetEmbeddedImTableEntry(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  static MemberOffset EmbeddedImTableEntryOffset(uint32_t i, size_t pointer_size);
 
-  void SetEmbeddedImTableEntry(uint32_t i, ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  static MemberOffset EmbeddedVTableEntryOffset(uint32_t i, size_t pointer_size);
+
+  ArtMethod* GetEmbeddedImTableEntry(uint32_t i, size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void SetEmbeddedImTableEntry(uint32_t i, ArtMethod* method, size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   int32_t GetVTableLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* GetVTableEntry(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* GetVTableEntry(uint32_t i, size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   int32_t GetEmbeddedVTableLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void SetEmbeddedVTableLength(int32_t len) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* GetEmbeddedVTableEntry(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* GetEmbeddedVTableEntry(uint32_t i, size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetEmbeddedVTableEntry(uint32_t i, ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetEmbeddedVTableEntry(uint32_t i, ArtMethod* method, size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void PopulateEmbeddedImtAndVTable(StackHandleScope<kImtSize>* imt_handle_scope)
+  inline void SetEmbeddedVTableEntryUnchecked(uint32_t i, ArtMethod* method, size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  void PopulateEmbeddedImtAndVTable(ArtMethod* const (&methods)[kImtSize], size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Given a method implemented by this class but potentially from a super class, return the
   // specific implementation method for this class.
-  ArtMethod* FindVirtualMethodForVirtual(ArtMethod* method)
+  ArtMethod* FindVirtualMethodForVirtual(ArtMethod* method, size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Given a method implemented by this class' super class, return the specific implementation
   // method for this class.
-  ArtMethod* FindVirtualMethodForSuper(ArtMethod* method)
+  ArtMethod* FindVirtualMethodForSuper(ArtMethod* method, size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Given a method implemented by this class, but potentially from a
   // super class or interface, return the specific implementation
   // method for this class.
-  ArtMethod* FindVirtualMethodForInterface(ArtMethod* method)
+  ArtMethod* FindVirtualMethodForInterface(ArtMethod* method, size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE;
 
-  ArtMethod* FindVirtualMethodForVirtualOrInterface(ArtMethod* method)
+  ArtMethod* FindVirtualMethodForVirtualOrInterface(ArtMethod* method, size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindInterfaceMethod(const StringPiece& name, const StringPiece& signature)
+  ArtMethod* FindInterfaceMethod(const StringPiece& name, const StringPiece& signature,
+                                 size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindInterfaceMethod(const StringPiece& name, const Signature& signature)
+  ArtMethod* FindInterfaceMethod(const StringPiece& name, const Signature& signature,
+                                 size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
+  ArtMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx,
+                                 size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature)
+  ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature,
+                                      size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature)
+  ArtMethod* FindDeclaredDirectMethod(const StringPiece& name, const Signature& signature,
+                                      size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
+  ArtMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx,
+                                      size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature)
+  ArtMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature,
+                              size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindDirectMethod(const StringPiece& name, const Signature& signature)
+  ArtMethod* FindDirectMethod(const StringPiece& name, const Signature& signature,
+                              size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
+  ArtMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx,
+                              size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature)
+  ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature,
+                                       size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature)
+  ArtMethod* FindDeclaredVirtualMethod(const StringPiece& name, const Signature& signature,
+                                       size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
+  ArtMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx,
+                                       size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& signature)
+  ArtMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& signature,
+                               size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindVirtualMethod(const StringPiece& name, const Signature& signature)
+  ArtMethod* FindVirtualMethod(const StringPiece& name, const Signature& signature,
+                               size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx)
+  ArtMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx,
+                               size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* FindClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* FindClassInitializer(size_t pointer_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   ALWAYS_INLINE int32_t GetIfTableCount() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -867,7 +916,8 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get the offset of the first reference instance field. Other reference instance fields follow.
-  MemberOffset GetFirstReferenceInstanceFieldOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  MemberOffset GetFirstReferenceInstanceFieldOffset()
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns the number of static fields containing reference types.
   uint32_t NumReferenceStaticFields() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -886,10 +936,11 @@
   }
 
   // Get the offset of the first reference static field. Other reference static fields follow.
-  MemberOffset GetFirstReferenceStaticFieldOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  MemberOffset GetFirstReferenceStaticFieldOffset(size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Get the offset of the first reference static field. Other reference static fields follow.
-  MemberOffset GetFirstReferenceStaticFieldOffsetDuringLinking()
+  MemberOffset GetFirstReferenceStaticFieldOffsetDuringLinking(size_t pointer_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Gets the static fields of the class.
@@ -989,22 +1040,20 @@
   static void VisitRoots(RootVisitor* visitor)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Visit native roots visits roots which are keyed off the native pointers such as ArtFields and
+  // ArtMethods.
   template<class Visitor>
-  // Visit field roots.
-  void VisitFieldRoots(Visitor& visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void VisitNativeRoots(Visitor& visitor, size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // When class is verified, set the kAccPreverified flag on each method.
-  void SetPreverifiedFlagOnAllMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetPreverifiedFlagOnAllMethods(size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template <bool kVisitClass, typename Visitor>
   void VisitReferences(mirror::Class* klass, const Visitor& visitor)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  // Visit references within the embedded tables of the class.
-  // TODO: remove NO_THREAD_SAFETY_ANALYSIS when annotalysis handles visitors better.
-  template<typename Visitor>
-  void VisitEmbeddedImtAndVTable(const Visitor& visitor) NO_THREAD_SAFETY_ANALYSIS;
-
   // Get the descriptor of the class. In a few cases a std::string is required, rather than
   // always create one the storage argument is populated and its internal c_str() returned. We do
   // this to avoid memory allocation in the common case.
@@ -1014,7 +1063,6 @@
 
   bool DescriptorEquals(const char* match) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-
   const DexFile::ClassDef* GetClassDef() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   ALWAYS_INLINE uint32_t NumDirectInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -1037,8 +1085,8 @@
   void AssertInitializedOrInitializingInThread(Thread* self)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  Class* CopyOf(Thread* self, int32_t new_length, StackHandleScope<kImtSize>* imt_handle_scope)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  Class* CopyOf(Thread* self, int32_t new_length, ArtMethod* const (&imt)[mirror::Class::kImtSize],
+                size_t pointer_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // For proxy class only.
   ObjectArray<Class>* GetInterfaces() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -1060,7 +1108,7 @@
   }
 
   // May cause thread suspension due to EqualParameters.
-  mirror::ArtMethod* GetDeclaredConstructor(
+  ArtMethod* GetDeclaredConstructor(
       Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -1085,6 +1133,20 @@
     return GetClassLoader() == nullptr;
   }
 
+  static size_t ImTableEntrySize(size_t pointer_size) {
+    return pointer_size;
+  }
+
+  static size_t VTableEntrySize(size_t pointer_size) {
+    return pointer_size;
+  }
+
+  ALWAYS_INLINE ArtMethod* GetDirectMethodsPtrUnchecked()
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  ALWAYS_INLINE ArtMethod* GetVirtualMethodsPtrUnchecked()
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
  private:
   void SetVerifyErrorClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -1109,6 +1171,12 @@
 
   bool ProxyDescriptorEquals(const char* match) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Check that the pointer size mathces the one in the class linker.
+  ALWAYS_INLINE static void CheckPointerSize(size_t pointer_size);
+
+  static MemberOffset EmbeddedImTableOffset(size_t pointer_size);
+  static MemberOffset EmbeddedVTableOffset(size_t pointer_size);
+
   // Defining class loader, or null for the "bootstrap" system loader.
   HeapReference<ClassLoader> class_loader_;
 
@@ -1123,9 +1191,6 @@
   // Short cuts to dex_cache_ member for fast compiled code access.
   HeapReference<ObjectArray<String>> dex_cache_strings_;
 
-  // static, private, and <init> methods
-  HeapReference<ObjectArray<ArtMethod>> direct_methods_;
-
   // The interface table (iftable_) contains pairs of a interface class and an array of the
   // interface methods. There is one pair per interface supported by this class.  That means one
   // pair for each interface we support directly, indirectly via superclass, or indirectly via a
@@ -1148,19 +1213,19 @@
   // If class verify fails, we must return same error on subsequent tries.
   HeapReference<Class> verify_error_class_;
 
-  // Virtual methods defined in this class; invoked through vtable.
-  HeapReference<ObjectArray<ArtMethod>> virtual_methods_;
-
   // Virtual method table (vtable), for use by "invoke-virtual".  The vtable from the superclass is
   // copied in, and virtual methods from our class either replace those from the super or are
   // appended. For abstract classes, methods may be created in the vtable that aren't in
   // virtual_ methods_ for miranda methods.
-  HeapReference<ObjectArray<ArtMethod>> vtable_;
+  HeapReference<PointerArray> vtable_;
 
   // Access flags; low 16 bits are defined by VM spec.
   // Note: Shuffled back.
   uint32_t access_flags_;
 
+  // static, private, and <init> methods. Pointer to an ArtMethod array.
+  uint64_t direct_methods_;
+
   // instance fields
   //
   // These describe the layout of the contents of an Object.
@@ -1174,6 +1239,9 @@
   // Static fields
   uint64_t sfields_;
 
+  // Virtual methods defined in this class; invoked through vtable. Pointer to an ArtMethod array.
+  uint64_t virtual_methods_;
+
   // Total size of the Class instance; used when allocating storage on gc heap.
   // See also object_size_.
   uint32_t class_size_;
@@ -1189,7 +1257,10 @@
   // TODO: really 16bits
   int32_t dex_type_idx_;
 
-  // Number of static fields.
+  // Number of direct fields.
+  uint32_t num_direct_methods_;
+
+  // Number of instance fields.
   uint32_t num_instance_fields_;
 
   // Number of instance fields that are object refs.
@@ -1201,6 +1272,9 @@
   // Number of static fields.
   uint32_t num_static_fields_;
 
+  // Number of virtual methods.
+  uint32_t num_virtual_methods_;
+
   // Total object size; used when allocating storage on gc heap.
   // (For interfaces and abstract classes this will be zero.)
   // See also class_size_.
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index bfb9eb5..4b5063a 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -20,6 +20,7 @@
 #include "dex_cache.h"
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "mirror/class.h"
 #include "runtime.h"
@@ -27,20 +28,9 @@
 namespace art {
 namespace mirror {
 
-inline uint32_t DexCache::ClassSize() {
+inline uint32_t DexCache::ClassSize(size_t pointer_size) {
   uint32_t vtable_entries = Object::kVTableLength + 5;
-  return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
-}
-
-inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ArtMethod* method = GetResolvedMethods()->Get(method_idx);
-  // Hide resolution trampoline methods from the caller
-  if (method != nullptr && method->IsRuntimeMethod()) {
-    DCHECK_EQ(method, Runtime::Current()->GetResolutionMethod());
-    return nullptr;
-  }
-  return method;
+  return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
 }
 
 inline void DexCache::SetResolvedType(uint32_t type_idx, Class* resolved) {
@@ -50,15 +40,8 @@
 }
 
 inline ArtField* DexCache::GetResolvedField(uint32_t idx, size_t ptr_size) {
-  ArtField* field = nullptr;
-  if (ptr_size == 8u) {
-    field = reinterpret_cast<ArtField*>(
-        static_cast<uintptr_t>(GetResolvedFields()->AsLongArray()->GetWithoutChecks(idx)));
-  } else {
-    DCHECK_EQ(ptr_size, 4u);
-    field = reinterpret_cast<ArtField*>(
-      static_cast<uintptr_t>(GetResolvedFields()->AsIntArray()->GetWithoutChecks(idx)));
-  }
+  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
+  auto* field = GetResolvedFields()->GetElementPtrSize<ArtField*>(idx, ptr_size);
   if (field == nullptr || field->GetDeclaringClass()->IsErroneous()) {
     return nullptr;
   }
@@ -66,15 +49,24 @@
 }
 
 inline void DexCache::SetResolvedField(uint32_t idx, ArtField* field, size_t ptr_size) {
-  if (ptr_size == 8u) {
-    GetResolvedFields()->AsLongArray()->Set(
-        idx, static_cast<uint64_t>(reinterpret_cast<uintptr_t>(field)));
-  } else {
-    DCHECK_EQ(ptr_size, 4u);
-    CHECK_LE(reinterpret_cast<uintptr_t>(field), 0xFFFFFFFF);
-    GetResolvedFields()->AsIntArray()->Set(
-        idx, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(field)));
+  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
+  GetResolvedFields()->SetElementPtrSize(idx, field, ptr_size);
+}
+
+inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx, size_t ptr_size) {
+  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
+  auto* method = GetResolvedMethods()->GetElementPtrSize<ArtMethod*>(method_idx, ptr_size);
+  // Hide resolution trampoline methods from the caller
+  if (method != nullptr && method->IsRuntimeMethod()) {
+    DCHECK_EQ(method, Runtime::Current()->GetResolutionMethod());
+    return nullptr;
   }
+  return method;
+}
+
+inline void DexCache::SetResolvedMethod(uint32_t idx, ArtMethod* method, size_t ptr_size) {
+  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
+  GetResolvedMethods()->SetElementPtrSize(idx, method, ptr_size);
 }
 
 }  // namespace mirror
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index ade8bd2..630faee 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -31,12 +31,9 @@
 namespace art {
 namespace mirror {
 
-void DexCache::Init(const DexFile* dex_file,
-                    String* location,
-                    ObjectArray<String>* strings,
-                    ObjectArray<Class>* resolved_types,
-                    ObjectArray<ArtMethod>* resolved_methods,
-                    Array* resolved_fields) {
+void DexCache::Init(const DexFile* dex_file, String* location, ObjectArray<String>* strings,
+                    ObjectArray<Class>* resolved_types, PointerArray* resolved_methods,
+                    PointerArray* resolved_fields, size_t pointer_size) {
   CHECK(dex_file != nullptr);
   CHECK(location != nullptr);
   CHECK(strings != nullptr);
@@ -51,24 +48,21 @@
   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_), resolved_types);
   SetFieldObject<false>(ResolvedMethodsOffset(), resolved_methods);
 
-  Runtime* runtime = Runtime::Current();
+  Runtime* const runtime = Runtime::Current();
   if (runtime->HasResolutionMethod()) {
     // Initialize the resolve methods array to contain trampolines for resolution.
-    ArtMethod* trampoline = runtime->GetResolutionMethod();
-    for (size_t i = 0, length = resolved_methods->GetLength(); i < length; i++) {
-      resolved_methods->SetWithoutChecks<false>(i, trampoline);
-    }
+    Fixup(runtime->GetResolutionMethod(), pointer_size);
   }
 }
 
-void DexCache::Fixup(ArtMethod* trampoline) {
+void DexCache::Fixup(ArtMethod* trampoline, size_t pointer_size) {
   // Fixup the resolve methods array to contain trampoline for resolution.
   CHECK(trampoline != nullptr);
-  ObjectArray<ArtMethod>* resolved_methods = GetResolvedMethods();
-  size_t length = resolved_methods->GetLength();
-  for (size_t i = 0; i < length; i++) {
-    if (resolved_methods->GetWithoutChecks(i) == nullptr) {
-      resolved_methods->SetWithoutChecks<false>(i, trampoline);
+  CHECK(trampoline->IsRuntimeMethod());
+  auto* resolved_methods = GetResolvedMethods();
+  for (size_t i = 0, length = resolved_methods->GetLength(); i < length; i++) {
+    if (resolved_methods->GetElementPtrSize<ArtMethod*>(i, pointer_size) == nullptr) {
+      resolved_methods->SetElementPtrSize(i, trampoline, pointer_size);
     }
   }
 }
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 7e30b89..0ce83ec 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_MIRROR_DEX_CACHE_H_
 #define ART_RUNTIME_MIRROR_DEX_CACHE_H_
 
+#include "array.h"
 #include "art_field.h"
 #include "art_method.h"
 #include "class.h"
@@ -38,22 +39,19 @@
 class MANAGED DexCache FINAL : public Object {
  public:
   // Size of java.lang.DexCache.class.
-  static uint32_t ClassSize();
+  static uint32_t ClassSize(size_t pointer_size);
 
   // Size of an instance of java.lang.DexCache not including referenced values.
   static constexpr uint32_t InstanceSize() {
     return sizeof(DexCache);
   }
 
-  void Init(const DexFile* dex_file,
-            String* location,
-            ObjectArray<String>* strings,
-            ObjectArray<Class>* types,
-            ObjectArray<ArtMethod>* methods,
-            Array* fields)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void Init(const DexFile* dex_file, String* location, ObjectArray<String>* strings,
+            ObjectArray<Class>* types, PointerArray* methods, PointerArray* fields,
+            size_t pointer_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void Fixup(ArtMethod* trampoline) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void Fixup(ArtMethod* trampoline, size_t pointer_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   String* GetLocation() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return GetFieldObject<String>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_));
@@ -109,19 +107,18 @@
   void SetResolvedType(uint32_t type_idx, Class* resolved)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ArtMethod* GetResolvedMethod(uint32_t method_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ALWAYS_INLINE ArtMethod* GetResolvedMethod(uint32_t method_idx, size_t ptr_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetResolvedMethod(uint32_t method_idx, ArtMethod* resolved) ALWAYS_INLINE
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    GetResolvedMethods()->Set(method_idx, resolved);
-  }
-
-  // Pointer sized variant, used for patching.
-  ArtField* GetResolvedField(uint32_t idx, size_t ptr_size)
+  ALWAYS_INLINE void SetResolvedMethod(uint32_t method_idx, ArtMethod* resolved, size_t ptr_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Pointer sized variant, used for patching.
-  void SetResolvedField(uint32_t idx, ArtField* field, size_t ptr_size)
+  ALWAYS_INLINE ArtField* GetResolvedField(uint32_t idx, size_t ptr_size)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  // Pointer sized variant, used for patching.
+  ALWAYS_INLINE void SetResolvedField(uint32_t idx, ArtField* field, size_t ptr_size)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   ObjectArray<String>* GetStrings() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -133,13 +130,12 @@
         OFFSET_OF_OBJECT_MEMBER(DexCache, resolved_types_));
   }
 
-  ObjectArray<ArtMethod>* GetResolvedMethods() ALWAYS_INLINE
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetFieldObject< ObjectArray<ArtMethod>>(ResolvedMethodsOffset());
+  PointerArray* GetResolvedMethods() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetFieldObject<PointerArray>(ResolvedMethodsOffset());
   }
 
-  Array* GetResolvedFields() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return GetFieldObject<Array>(ResolvedFieldsOffset());
+  PointerArray* GetResolvedFields() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return GetFieldObject<PointerArray>(ResolvedFieldsOffset());
   }
 
   const DexFile* GetDexFile() ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -154,9 +150,9 @@
  private:
   HeapReference<Object> dex_;
   HeapReference<String> location_;
-  // Either an int array or long array (64 bit).
-  HeapReference<Object> resolved_fields_;
-  HeapReference<ObjectArray<ArtMethod>> resolved_methods_;
+  // Either an int array or long array based on runtime ISA since these arrays hold pointers.
+  HeapReference<PointerArray> resolved_fields_;
+  HeapReference<PointerArray> resolved_methods_;
   HeapReference<ObjectArray<Class>> resolved_types_;
   HeapReference<ObjectArray<String>> strings_;
   uint64_t dex_file_;
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index 388921b..8a0daec 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -50,14 +50,14 @@
     }
   }
   auto ret = hs.NewHandle(static_cast<Field*>(StaticClass()->AllocObject(self)));
-  if (ret.Get() == nullptr) {
-    if (kIsDebugBuild) {
-      self->AssertPendingException();
-    }
+  if (UNLIKELY(ret.Get() == nullptr)) {
+    self->AssertPendingOOMException();
     return nullptr;
   }
+  const auto pointer_size = kTransactionActive ?
+      Runtime::Current()->GetClassLinker()->GetImagePointerSize() : sizeof(void*);
   auto dex_field_index = field->GetDexFieldIndex();
-  auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index, sizeof(void*));
+  auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index, pointer_size);
   if (field->GetDeclaringClass()->IsProxyClass()) {
     DCHECK(field->IsStatic());
     DCHECK_LT(dex_field_index, 2U);
@@ -70,7 +70,7 @@
     } else {
       // We rely on the field being resolved so that we can back to the ArtField
       // (i.e. FromReflectedMethod).
-      field->GetDexCache()->SetResolvedField(dex_field_index, field, sizeof(void*));
+      field->GetDexCache()->SetResolvedField(dex_field_index, field, pointer_size);
     }
   }
   ret->SetType<kTransactionActive>(type.Get());
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
index ac56129..02e4484 100644
--- a/runtime/mirror/field.cc
+++ b/runtime/mirror/field.cc
@@ -16,6 +16,7 @@
 
 #include "field-inl.h"
 
+#include "class-inl.h"
 #include "dex_cache-inl.h"
 #include "object_array-inl.h"
 #include "object-inl.h"
diff --git a/runtime/mirror/iftable.h b/runtime/mirror/iftable.h
index 1c1c7b3..1ea5bee 100644
--- a/runtime/mirror/iftable.h
+++ b/runtime/mirror/iftable.h
@@ -34,27 +34,22 @@
   ALWAYS_INLINE void SetInterface(int32_t i, Class* interface)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  ObjectArray<ArtMethod>* GetMethodArray(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    ObjectArray<ArtMethod>* method_array =
-        down_cast<ObjectArray<ArtMethod>*>(Get((i * kMax) + kMethodArray));
+  PointerArray* GetMethodArray(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    auto* method_array = down_cast<PointerArray*>(Get((i * kMax) + kMethodArray));
     DCHECK(method_array != nullptr);
     return method_array;
   }
 
   size_t GetMethodArrayCount(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    ObjectArray<ArtMethod>* method_array =
-        down_cast<ObjectArray<ArtMethod>*>(Get((i * kMax) + kMethodArray));
-    if (method_array == nullptr) {
-      return 0;
-    }
-    return method_array->GetLength();
+    auto* method_array = down_cast<PointerArray*>(Get((i * kMax) + kMethodArray));
+    return method_array == nullptr ? 0u : method_array->GetLength();
   }
 
-  void SetMethodArray(int32_t i, ObjectArray<ArtMethod>* new_ma)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(new_ma != nullptr);
-    DCHECK(Get((i * kMax) + kMethodArray) == nullptr);
-    Set<false>((i * kMax) + kMethodArray, new_ma);
+  void SetMethodArray(int32_t i, PointerArray* arr) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    DCHECK(arr != nullptr);
+    auto idx = i * kMax + kMethodArray;
+    DCHECK(Get(idx) == nullptr);
+    Set<false>(idx, arr);
   }
 
   size_t Count() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
index 81530bb..85c52e9 100644
--- a/runtime/mirror/method.cc
+++ b/runtime/mirror/method.cc
@@ -16,7 +16,9 @@
 
 #include "method.h"
 
-#include "mirror/art_method.h"
+#include "art_method.h"
+#include "gc_root-inl.h"
+#include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 
 namespace art {
@@ -49,7 +51,7 @@
   array_class_ = GcRoot<Class>(nullptr);
 }
 
-Method* Method::CreateFromArtMethod(Thread* self, mirror::ArtMethod* method) {
+Method* Method::CreateFromArtMethod(Thread* self, ArtMethod* method) {
   DCHECK(!method->IsConstructor()) << PrettyMethod(method);
   auto* ret = down_cast<Method*>(StaticClass()->AllocObject(self));
   if (LIKELY(ret != nullptr)) {
@@ -90,7 +92,7 @@
   array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
 }
 
-Constructor* Constructor::CreateFromArtMethod(Thread* self, mirror::ArtMethod* method) {
+Constructor* Constructor::CreateFromArtMethod(Thread* self, ArtMethod* method) {
   DCHECK(method->IsConstructor()) << PrettyMethod(method);
   auto* ret = down_cast<Constructor*>(StaticClass()->AllocObject(self));
   if (LIKELY(ret != nullptr)) {
diff --git a/runtime/mirror/method.h b/runtime/mirror/method.h
index 88100f0..42c76c0 100644
--- a/runtime/mirror/method.h
+++ b/runtime/mirror/method.h
@@ -28,7 +28,7 @@
 // C++ mirror of java.lang.reflect.Method.
 class MANAGED Method : public AbstractMethod {
  public:
-  static Method* CreateFromArtMethod(Thread* self, mirror::ArtMethod* method)
+  static Method* CreateFromArtMethod(Thread* self, ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static mirror::Class* StaticClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -59,7 +59,7 @@
 // C++ mirror of java.lang.reflect.Constructor.
 class MANAGED Constructor: public AbstractMethod {
  public:
-  static Constructor* CreateFromArtMethod(Thread* self, mirror::ArtMethod* method)
+  static Constructor* CreateFromArtMethod(Thread* self, ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static mirror::Class* StaticClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 7760ea2..e019d5a 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -24,6 +24,7 @@
 #include "atomic.h"
 #include "array-inl.h"
 #include "class.h"
+#include "class_linker.h"
 #include "lock_word-inl.h"
 #include "monitor.h"
 #include "object_array-inl.h"
@@ -36,9 +37,9 @@
 namespace art {
 namespace mirror {
 
-inline uint32_t Object::ClassSize() {
+inline uint32_t Object::ClassSize(size_t pointer_size) {
   uint32_t vtable_entries = kVTableLength;
-  return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
+  return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
 }
 
 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
@@ -257,18 +258,6 @@
       template IsArrayClass<kVerifyFlags, kReadBarrierOption>();
 }
 
-template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
-inline bool Object::IsArtMethod() {
-  return GetClass<kVerifyFlags, kReadBarrierOption>()->
-      template IsArtMethodClass<kReadBarrierOption>();
-}
-
-template<VerifyObjectFlags kVerifyFlags>
-inline ArtMethod* Object::AsArtMethod() {
-  DCHECK(IsArtMethod<kVerifyFlags>());
-  return down_cast<ArtMethod*>(this);
-}
-
 template<VerifyObjectFlags kVerifyFlags>
 inline bool Object::IsReferenceInstance() {
   return GetClass<kVerifyFlags>()->IsTypeOfReferenceClass();
@@ -296,7 +285,7 @@
 
 template<VerifyObjectFlags kVerifyFlags>
 inline ByteArray* Object::AsByteArray() {
-  static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
   return down_cast<ByteArray*>(this);
@@ -304,7 +293,7 @@
 
 template<VerifyObjectFlags kVerifyFlags>
 inline ByteArray* Object::AsByteSizedArray() {
-  constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
          GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
@@ -337,25 +326,41 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline IntArray* Object::AsIntArray() {
+inline bool Object::IsIntArray() {
   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
-  CHECK(GetClass<kVerifyFlags>()->IsArrayClass());
-  CHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() ||
-         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
+  auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
+  return component_type != nullptr && component_type->template IsPrimitiveInt<kNewFlags>();
+}
+
+template<VerifyObjectFlags kVerifyFlags>
+inline IntArray* Object::AsIntArray() {
+  DCHECK(IsIntArray<kVerifyFlags>());
   return down_cast<IntArray*>(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline LongArray* Object::AsLongArray() {
+inline bool Object::IsLongArray() {
   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
-  CHECK(GetClass<kVerifyFlags>()->IsArrayClass());
-  CHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() ||
-         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
+  auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
+  return component_type != nullptr && component_type->template IsPrimitiveLong<kNewFlags>();
+}
+
+template<VerifyObjectFlags kVerifyFlags>
+inline LongArray* Object::AsLongArray() {
+  DCHECK(IsLongArray<kVerifyFlags>());
   return down_cast<LongArray*>(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
+inline bool Object::IsFloatArray() {
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
+  return component_type != nullptr && component_type->template IsPrimitiveFloat<kNewFlags>();
+}
+
+template<VerifyObjectFlags kVerifyFlags>
 inline FloatArray* Object::AsFloatArray() {
+  DCHECK(IsFloatArray<kVerifyFlags>());
   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
@@ -363,7 +368,15 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
+inline bool Object::IsDoubleArray() {
+  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+  auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
+  return component_type != nullptr && component_type->template IsPrimitiveDouble<kNewFlags>();
+}
+
+template<VerifyObjectFlags kVerifyFlags>
 inline DoubleArray* Object::AsDoubleArray() {
+  DCHECK(IsDoubleArray<kVerifyFlags>());
   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
@@ -954,8 +967,11 @@
       if (num_reference_fields == 0u) {
         continue;
       }
+      // Presumably GC can happen when we are cross compiling, it should not cause performance
+      // problems to do pointer size logic.
       MemberOffset field_offset = kIsStatic
-          ? klass->GetFirstReferenceStaticFieldOffset()
+          ? klass->GetFirstReferenceStaticFieldOffset(
+              Runtime::Current()->GetClassLinker()->GetImagePointerSize())
           : klass->GetFirstReferenceInstanceFieldOffset();
       for (size_t i = 0; i < num_reference_fields; ++i) {
         // TODO: Do a simpler check?
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index f9740bb..b177e2f 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -106,9 +106,8 @@
       : self_(self), orig_(orig), num_bytes_(num_bytes) {
   }
 
-  void operator()(Object* obj, size_t usable_size) const
+  void operator()(Object* obj, size_t usable_size ATTRIBUTE_UNUSED) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    UNUSED(usable_size);
     Object::CopyObject(self_, obj, orig_->Get(), num_bytes_);
   }
 
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 2c0e626..744e7b5 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -25,6 +25,7 @@
 namespace art {
 
 class ArtField;
+class ArtMethod;
 class ImageWriter;
 class LockWord;
 class Monitor;
@@ -34,7 +35,6 @@
 
 namespace mirror {
 
-class ArtMethod;
 class Array;
 class Class;
 class FinalizerReference;
@@ -71,7 +71,7 @@
   static constexpr size_t kVTableLength = 11;
 
   // The size of the java.lang.Class representing a java.lang.Object.
-  static uint32_t ClassSize();
+  static uint32_t ClassSize(size_t pointer_size);
 
   // Size of an instance of java.lang.Object.
   static constexpr uint32_t InstanceSize() {
@@ -178,12 +178,22 @@
   ShortArray* AsShortSizedArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  bool IsIntArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   IntArray* AsIntArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  bool IsLongArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   LongArray* AsLongArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  bool IsFloatArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   FloatArray* AsFloatArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+  bool IsDoubleArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   DoubleArray* AsDoubleArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -198,12 +208,6 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   Throwable* AsThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
-           ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  bool IsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ArtMethod* AsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index 6404faf..5eddc18 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -26,8 +26,8 @@
 class MANAGED ObjectArray: public Array {
  public:
   // The size of Object[].class.
-  static uint32_t ClassSize() {
-    return Array::ClassSize();
+  static uint32_t ClassSize(size_t pointer_size) {
+    return Array::ClassSize(pointer_size);
   }
 
   static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length,
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 8e50a7a..85ea28f 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -77,9 +77,9 @@
 TEST_F(ObjectTest, Constants) {
   EXPECT_EQ(kObjectReferenceSize, sizeof(HeapReference<Object>));
   EXPECT_EQ(kObjectHeaderSize, sizeof(Object));
-  EXPECT_EQ(MIRROR_ART_METHOD_QUICK_CODE_OFFSET_32,
+  EXPECT_EQ(ART_METHOD_QUICK_CODE_OFFSET_32,
             ArtMethod::EntryPointFromQuickCompiledCodeOffset(4).Int32Value());
-  EXPECT_EQ(MIRROR_ART_METHOD_QUICK_CODE_OFFSET_64,
+  EXPECT_EQ(ART_METHOD_QUICK_CODE_OFFSET_64,
             ArtMethod::EntryPointFromQuickCompiledCodeOffset(8).Int32Value());
 }
 
@@ -306,7 +306,7 @@
   // pretend we are trying to call 'new char[3]' from String.toCharArray
   ScopedObjectAccess soa(Thread::Current());
   Class* java_util_Arrays = class_linker_->FindSystemClass(soa.Self(), "Ljava/util/Arrays;");
-  ArtMethod* sort = java_util_Arrays->FindDirectMethod("sort", "([I)V");
+  ArtMethod* sort = java_util_Arrays->FindDirectMethod("sort", "([I)V", sizeof(void*));
   const DexFile::StringId* string_id = java_lang_dex_file_->FindStringId("[I");
   ASSERT_TRUE(string_id != nullptr);
   const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(
@@ -366,7 +366,7 @@
   StackHandleScope<2> hs(soa.Self());
   Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<ClassLoader*>(class_loader)));
   Class* klass = class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", loader);
-  ArtMethod* clinit = klass->FindClassInitializer();
+  ArtMethod* clinit = klass->FindClassInitializer(sizeof(void*));
   const DexFile::StringId* klass_string_id = dex_file->FindStringId("LStaticsFromCode;");
   ASSERT_TRUE(klass_string_id != nullptr);
   const DexFile::TypeId* klass_type_id = dex_file->FindTypeId(
@@ -508,22 +508,22 @@
   Class* klass2 = linker->FindClass(soa.Self(), "LProtoCompare2;", class_loader_2);
   ASSERT_TRUE(klass2 != nullptr);
 
-  ArtMethod* m1_1 = klass1->GetVirtualMethod(0);
+  ArtMethod* m1_1 = klass1->GetVirtualMethod(0, sizeof(void*));
   EXPECT_STREQ(m1_1->GetName(), "m1");
-  ArtMethod* m2_1 = klass1->GetVirtualMethod(1);
+  ArtMethod* m2_1 = klass1->GetVirtualMethod(1, sizeof(void*));
   EXPECT_STREQ(m2_1->GetName(), "m2");
-  ArtMethod* m3_1 = klass1->GetVirtualMethod(2);
+  ArtMethod* m3_1 = klass1->GetVirtualMethod(2, sizeof(void*));
   EXPECT_STREQ(m3_1->GetName(), "m3");
-  ArtMethod* m4_1 = klass1->GetVirtualMethod(3);
+  ArtMethod* m4_1 = klass1->GetVirtualMethod(3, sizeof(void*));
   EXPECT_STREQ(m4_1->GetName(), "m4");
 
-  ArtMethod* m1_2 = klass2->GetVirtualMethod(0);
+  ArtMethod* m1_2 = klass2->GetVirtualMethod(0, sizeof(void*));
   EXPECT_STREQ(m1_2->GetName(), "m1");
-  ArtMethod* m2_2 = klass2->GetVirtualMethod(1);
+  ArtMethod* m2_2 = klass2->GetVirtualMethod(1, sizeof(void*));
   EXPECT_STREQ(m2_2->GetName(), "m2");
-  ArtMethod* m3_2 = klass2->GetVirtualMethod(2);
+  ArtMethod* m3_2 = klass2->GetVirtualMethod(2, sizeof(void*));
   EXPECT_STREQ(m3_2->GetName(), "m3");
-  ArtMethod* m4_2 = klass2->GetVirtualMethod(3);
+  ArtMethod* m4_2 = klass2->GetVirtualMethod(3, sizeof(void*));
   EXPECT_STREQ(m4_2->GetName(), "m4");
 }
 
diff --git a/runtime/mirror/reference-inl.h b/runtime/mirror/reference-inl.h
index d1d2a3a..01e99b9 100644
--- a/runtime/mirror/reference-inl.h
+++ b/runtime/mirror/reference-inl.h
@@ -22,9 +22,9 @@
 namespace art {
 namespace mirror {
 
-inline uint32_t Reference::ClassSize() {
+inline uint32_t Reference::ClassSize(size_t pointer_size) {
   uint32_t vtable_entries = Object::kVTableLength + 5;
-  return Class::ComputeClassSize(false, vtable_entries, 2, 0, 0, 0, 0);
+  return Class::ComputeClassSize(false, vtable_entries, 2, 0, 0, 0, 0, pointer_size);
 }
 
 inline bool Reference::IsEnqueuable() {
diff --git a/runtime/mirror/reference.cc b/runtime/mirror/reference.cc
index 70bcf92..3c7f8c8 100644
--- a/runtime/mirror/reference.cc
+++ b/runtime/mirror/reference.cc
@@ -16,7 +16,7 @@
 
 #include "reference.h"
 
-#include "mirror/art_method.h"
+#include "art_method.h"
 #include "gc_root-inl.h"
 
 namespace art {
diff --git a/runtime/mirror/reference.h b/runtime/mirror/reference.h
index c11d79d..4bbdb99 100644
--- a/runtime/mirror/reference.h
+++ b/runtime/mirror/reference.h
@@ -42,7 +42,7 @@
 class MANAGED Reference : public Object {
  public:
   // Size of java.lang.ref.Reference.class.
-  static uint32_t ClassSize();
+  static uint32_t ClassSize(size_t pointer_size);
 
   // Size of an instance of java.lang.ref.Reference.
   static constexpr uint32_t InstanceSize() {
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index 35b8aef..9f6cd11 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -30,9 +30,9 @@
 namespace art {
 namespace mirror {
 
-inline uint32_t String::ClassSize() {
+inline uint32_t String::ClassSize(size_t pointer_size) {
   uint32_t vtable_entries = Object::kVTableLength + 52;
-  return Class::ComputeClassSize(true, vtable_entries, 0, 1, 0, 1, 2);
+  return Class::ComputeClassSize(true, vtable_entries, 0, 1, 0, 1, 2, pointer_size);
 }
 
 // Sets string count in the allocation code path to ensure it is guarded by a CAS.
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index fcfe976..a8f16d7 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -34,7 +34,7 @@
 class MANAGED String FINAL : public Object {
  public:
   // Size of java.lang.String.class.
-  static uint32_t ClassSize();
+  static uint32_t ClassSize(size_t pointer_size);
 
   // Size of an instance of java.lang.String not including its value array.
   static constexpr uint32_t InstanceSize() {
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index 782b9c0..224d266 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -86,17 +86,21 @@
   result += "\n";
   Object* stack_state = GetStackState();
   // check stack state isn't missing or corrupt
-  if (stack_state != nullptr && stack_state->IsObjectArray()) {
+  if (stack_state != nullptr &&
+      (stack_state->IsIntArray() || stack_state->IsLongArray())) {
     // Decode the internal stack trace into the depth and method trace
-    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));
+    // Format is [method pointers][pcs]
+    auto* method_trace = down_cast<mirror::PointerArray*>(stack_state->AsArray());
+    auto array_len = method_trace->GetLength();
+    CHECK_EQ(array_len % 2, 0);
+    const auto depth = array_len / 2;
     if (depth == 0) {
       result += "(Throwable with empty stack trace)";
     } else {
+      auto ptr_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
       for (int32_t i = 0; i < depth; ++i) {
-        mirror::ArtMethod* method = down_cast<ArtMethod*>(method_trace->Get(i));
-        uint32_t dex_pc = pc_trace->Get(i);
+        ArtMethod* method = method_trace->GetElementPtrSize<ArtMethod*>(i, ptr_size);
+        uintptr_t dex_pc = method_trace->GetElementPtrSize<uintptr_t>(i + depth, ptr_size);
         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(),
@@ -108,8 +112,7 @@
     if (stack_trace != nullptr && stack_trace->IsObjectArray()) {
       CHECK_EQ(stack_trace->GetClass()->GetComponentType(),
                StackTraceElement::GetStackTraceElement());
-      ObjectArray<StackTraceElement>* ste_array =
-          down_cast<ObjectArray<StackTraceElement>*>(stack_trace);
+      auto* ste_array = down_cast<ObjectArray<StackTraceElement>*>(stack_trace);
       if (ste_array->GetLength() == 0) {
         result += "(Throwable with empty stack trace)";
       } else {
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index dc016a5..4be25d6 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -21,6 +21,7 @@
 #include <cutils/trace.h>
 #include <vector>
 
+#include "art_method-inl.h"
 #include "base/mutex.h"
 #include "base/stl_util.h"
 #include "base/time_utils.h"
@@ -28,7 +29,6 @@
 #include "dex_file-inl.h"
 #include "dex_instruction.h"
 #include "lock_word-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
@@ -245,7 +245,7 @@
     // Contended.
     const bool log_contention = (lock_profiling_threshold_ != 0);
     uint64_t wait_start_ms = log_contention ? MilliTime() : 0;
-    mirror::ArtMethod* owners_method = locking_method_;
+    ArtMethod* owners_method = locking_method_;
     uint32_t owners_dex_pc = locking_dex_pc_;
     // Do this before releasing the lock so that we don't get deflated.
     size_t num_waiters = num_waiters_;
@@ -449,7 +449,7 @@
   int prev_lock_count = lock_count_;
   lock_count_ = 0;
   owner_ = nullptr;
-  mirror::ArtMethod* saved_method = locking_method_;
+  ArtMethod* saved_method = locking_method_;
   locking_method_ = nullptr;
   uintptr_t saved_dex_pc = locking_dex_pc_;
   locking_dex_pc_ = 0;
@@ -994,14 +994,15 @@
 
 void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::Object*, void*),
                          void* callback_context, bool abort_on_failure) {
-  mirror::ArtMethod* m = stack_visitor->GetMethod();
+  ArtMethod* m = stack_visitor->GetMethod();
   CHECK(m != nullptr);
 
   // Native methods are an easy special case.
   // TODO: use the JNI implementation's table of explicit MonitorEnter calls and dump those too.
   if (m->IsNative()) {
     if (m->IsSynchronized()) {
-      mirror::Object* jni_this = stack_visitor->GetCurrentHandleScope()->GetReference(0);
+      mirror::Object* jni_this =
+          stack_visitor->GetCurrentHandleScope(sizeof(void*))->GetReference(0);
       callback(jni_this, callback_context);
     }
     return;
@@ -1087,7 +1088,7 @@
   return owner_ != nullptr;
 }
 
-void Monitor::TranslateLocation(mirror::ArtMethod* method, uint32_t dex_pc,
+void Monitor::TranslateLocation(ArtMethod* method, uint32_t dex_pc,
                                 const char** source_file, uint32_t* line_number) const {
   // If method is null, location is unknown
   if (method == nullptr) {
diff --git a/runtime/monitor.h b/runtime/monitor.h
index b7245c1..8f3a91d 100644
--- a/runtime/monitor.h
+++ b/runtime/monitor.h
@@ -36,14 +36,14 @@
 
 namespace art {
 
+class ArtMethod;
 class LockWord;
 template<class T> class Handle;
-class Thread;
 class StackVisitor;
+class Thread;
 typedef uint32_t MonitorId;
 
 namespace mirror {
-  class ArtMethod;
   class Object;
 }  // namespace mirror
 
@@ -226,7 +226,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Translates the provided method and pc into its declaring class' source file and line number.
-  void TranslateLocation(mirror::ArtMethod* method, uint32_t pc,
+  void TranslateLocation(ArtMethod* method, uint32_t pc,
                          const char** source_file, uint32_t* line_number) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -262,7 +262,7 @@
   // Method and dex pc where the lock owner acquired the lock, used when lock
   // sampling is enabled. locking_method_ may be null if the lock is currently
   // unlocked, or if the lock is acquired by the system when the stack is empty.
-  mirror::ArtMethod* locking_method_ GUARDED_BY(monitor_lock_);
+  ArtMethod* locking_method_ GUARDED_BY(monitor_lock_);
   uint32_t locking_dex_pc_ GUARDED_BY(monitor_lock_);
 
   // The denser encoded version of this monitor as stored in the lock word.
diff --git a/runtime/monitor_android.cc b/runtime/monitor_android.cc
index 48c9cce..efe2e82 100644
--- a/runtime/monitor_android.cc
+++ b/runtime/monitor_android.cc
@@ -78,7 +78,7 @@
 
   // Emit the source code file name, <= 37 bytes.
   uint32_t pc;
-  mirror::ArtMethod* m = self->GetCurrentMethod(&pc);
+  ArtMethod* m = self->GetCurrentMethod(&pc);
   const char* filename;
   uint32_t line_number;
   TranslateLocation(m, pc, &filename, &line_number);
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index a172197..5dd354d 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -27,6 +27,7 @@
 #include "toStringArray.h"
 #pragma GCC diagnostic pop
 
+#include "art_method-inl.h"
 #include "arch/instruction_set.h"
 #include "class_linker-inl.h"
 #include "common_throws.h"
@@ -40,7 +41,6 @@
 #include "gc/task_processor.h"
 #include "intern_table.h"
 #include "jni_internal.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/object-inl.h"
@@ -350,7 +350,7 @@
 static void PreloadDexCachesResolveMethod(Handle<mirror::DexCache> dex_cache, uint32_t method_idx,
                                           InvokeType invoke_type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ArtMethod* method = dex_cache->GetResolvedMethod(method_idx);
+  ArtMethod* method = dex_cache->GetResolvedMethod(method_idx, sizeof(void*));
   if (method != nullptr) {
     return;
   }
@@ -363,14 +363,14 @@
   switch (invoke_type) {
     case kDirect:
     case kStatic:
-      method = klass->FindDirectMethod(dex_cache.Get(), method_idx);
+      method = klass->FindDirectMethod(dex_cache.Get(), method_idx, sizeof(void*));
       break;
     case kInterface:
-      method = klass->FindInterfaceMethod(dex_cache.Get(), method_idx);
+      method = klass->FindInterfaceMethod(dex_cache.Get(), method_idx, sizeof(void*));
       break;
     case kSuper:
     case kVirtual:
-      method = klass->FindVirtualMethod(dex_cache.Get(), method_idx);
+      method = klass->FindVirtualMethod(dex_cache.Get(), method_idx, sizeof(void*));
       break;
     default:
       LOG(FATAL) << "Unreachable - invocation type: " << invoke_type;
@@ -380,7 +380,7 @@
     return;
   }
   // LOG(INFO) << "VMRuntime.preloadDexCaches resolved method " << PrettyMethod(method);
-  dex_cache->SetResolvedMethod(method_idx, method);
+  dex_cache->SetResolvedMethod(method_idx, method, sizeof(void*));
 }
 
 struct DexCacheStats {
@@ -452,7 +452,7 @@
       }
     }
     for (size_t j = 0; j < dex_cache->NumResolvedMethods(); j++) {
-      mirror::ArtMethod* method = dex_cache->GetResolvedMethod(j);
+      ArtMethod* method = dex_cache->GetResolvedMethod(j, sizeof(void*));
       if (method != nullptr) {
         filled->num_methods++;
       }
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
index 1d7d853..ee62755 100644
--- a/runtime/native/dalvik_system_VMStack.cc
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -16,9 +16,9 @@
 
 #include "dalvik_system_VMStack.h"
 
+#include "art_method-inl.h"
 #include "jni_internal.h"
 #include "nth_caller_visitor.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
@@ -90,10 +90,13 @@
     bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
       DCHECK(class_loader == nullptr);
       mirror::Class* c = GetMethod()->GetDeclaringClass();
-      mirror::Object* cl = c->GetClassLoader();
-      if (cl != nullptr) {
-        class_loader = cl;
-        return false;
+      // c is null for runtime methods.
+      if (c != nullptr) {
+        mirror::Object* cl = c->GetClassLoader();
+        if (cl != nullptr) {
+          class_loader = cl;
+          return false;
+        }
       }
       return true;
     }
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 795a0ea..94024ef 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -273,7 +273,7 @@
   return nullptr;
 }
 
-static ALWAYS_INLINE inline bool MethodMatchesConstructor(mirror::ArtMethod* m, bool public_only)
+static ALWAYS_INLINE inline bool MethodMatchesConstructor(ArtMethod* m, bool public_only)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(m != nullptr);
   return (!public_only || m->IsPublic()) && !m->IsStatic() && m->IsConstructor();
@@ -283,14 +283,11 @@
     JNIEnv* env, jobject javaThis, jboolean publicOnly) {
   ScopedFastNativeObjectAccess soa(env);
   auto* klass = DecodeClass(soa, javaThis);
-  StackHandleScope<2> hs(soa.Self());
-  auto h_direct_methods = hs.NewHandle(klass->GetDirectMethods());
+  StackHandleScope<1> hs(soa.Self());
   size_t constructor_count = 0;
-  auto count = h_direct_methods.Get() != nullptr ? h_direct_methods->GetLength() : 0u;
   // Two pass approach for speed.
-  for (size_t i = 0; i < count; ++i) {
-    constructor_count += MethodMatchesConstructor(h_direct_methods->GetWithoutChecks(i),
-                                                  publicOnly != JNI_FALSE) ? 1u : 0u;
+  for (auto& m : klass->GetDirectMethods(sizeof(void*))) {
+    constructor_count += MethodMatchesConstructor(&m, publicOnly != JNI_FALSE) ? 1u : 0u;
   }
   auto h_constructors = hs.NewHandle(mirror::ObjectArray<mirror::Constructor>::Alloc(
       soa.Self(), mirror::Constructor::ArrayClass(), constructor_count));
@@ -299,12 +296,11 @@
     return nullptr;
   }
   constructor_count = 0;
-  for (size_t i = 0; i < count; ++i) {
-    auto* method = h_direct_methods->GetWithoutChecks(i);
-    if (MethodMatchesConstructor(method, publicOnly != JNI_FALSE)) {
-      auto* constructor = mirror::Constructor::CreateFromArtMethod(soa.Self(), method);
+  for (auto& m : klass->GetDirectMethods(sizeof(void*))) {
+    if (MethodMatchesConstructor(&m, publicOnly != JNI_FALSE)) {
+      auto* constructor = mirror::Constructor::CreateFromArtMethod(soa.Self(), &m);
       if (UNLIKELY(constructor == nullptr)) {
-        soa.Self()->AssertPendingException();
+        soa.Self()->AssertPendingOOMException();
         return nullptr;
       }
       h_constructors->SetWithoutChecks<false>(constructor_count++, constructor);
@@ -323,7 +319,7 @@
   // were synthesized by the runtime.
   constexpr uint32_t kSkipModifiers = kAccMiranda | kAccSynthetic;
   ScopedFastNativeObjectAccess soa(env);
-  StackHandleScope<5> hs(soa.Self());
+  StackHandleScope<4> hs(soa.Self());
   auto h_method_name = hs.NewHandle(soa.Decode<mirror::String*>(name));
   if (UNLIKELY(h_method_name.Get() == nullptr)) {
     ThrowNullPointerException("name == null");
@@ -331,60 +327,49 @@
   }
   auto h_args = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
   auto* klass = DecodeClass(soa, javaThis);
-  mirror::ArtMethod* result = nullptr;
-  auto* virtual_methods = klass->GetVirtualMethods();
-  if (virtual_methods != nullptr) {
-    auto h_virtual_methods = hs.NewHandle(virtual_methods);
-    for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
-      auto* m = h_virtual_methods->GetWithoutChecks(i);
-      auto* np_method = m->GetInterfaceMethodIfProxy();
+  ArtMethod* result = nullptr;
+  for (auto& m : klass->GetVirtualMethods(sizeof(void*))) {
+    auto* np_method = m.GetInterfaceMethodIfProxy(sizeof(void*));
+    // May cause thread suspension.
+    mirror::String* np_name = np_method->GetNameAsString(soa.Self());
+    if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
+      if (UNLIKELY(soa.Self()->IsExceptionPending())) {
+        return nullptr;
+      }
+      continue;
+    }
+    auto modifiers = m.GetAccessFlags();
+    if ((modifiers & kSkipModifiers) == 0) {
+      return soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(soa.Self(), &m));
+    }
+    if ((modifiers & kAccMiranda) == 0) {
+      result = &m;  // Remember as potential result if it's not a miranda method.
+    }
+  }
+  if (result == nullptr) {
+    for (auto& m : klass->GetDirectMethods(sizeof(void*))) {
+      auto modifiers = m.GetAccessFlags();
+      if ((modifiers & kAccConstructor) != 0) {
+        continue;
+      }
+      auto* np_method = m.GetInterfaceMethodIfProxy(sizeof(void*));
       // May cause thread suspension.
       mirror::String* np_name = np_method->GetNameAsString(soa.Self());
+      if (np_name == nullptr) {
+        soa.Self()->AssertPendingException();
+        return nullptr;
+      }
       if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
         if (UNLIKELY(soa.Self()->IsExceptionPending())) {
           return nullptr;
         }
         continue;
       }
-      auto modifiers = m->GetAccessFlags();
       if ((modifiers & kSkipModifiers) == 0) {
-        return soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(soa.Self(), m));
+        return soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(soa.Self(), &m));
       }
-      if ((modifiers & kAccMiranda) == 0) {
-        result = m;  // Remember as potential result if it's not a miranda method.
-      }
-    }
-  }
-  if (result == nullptr) {
-    auto* direct_methods = klass->GetDirectMethods();
-    if (direct_methods != nullptr) {
-      auto h_direct_methods = hs.NewHandle(direct_methods);
-      for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
-        auto* m = h_direct_methods->GetWithoutChecks(i);
-        auto modifiers = m->GetAccessFlags();
-        if ((modifiers & kAccConstructor) != 0) {
-          continue;
-        }
-        auto* np_method = m->GetInterfaceMethodIfProxy();
-        // May cause thread suspension.
-        mirror::String* np_name = np_method ->GetNameAsString(soa.Self());
-        if (np_name == nullptr) {
-          soa.Self()->AssertPendingException();
-          return nullptr;
-        }
-        if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
-          if (UNLIKELY(soa.Self()->IsExceptionPending())) {
-            return nullptr;
-          }
-          continue;
-        }
-        if ((modifiers & kSkipModifiers) == 0) {
-          return soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(
-              soa.Self(), m));
-        }
-        // Direct methods cannot be miranda methods, so this potential result must be synthetic.
-        result = m;
-      }
+      // Direct methods cannot be miranda methods, so this potential result must be synthetic.
+      result = &m;
     }
   }
   return result != nullptr ?
@@ -395,64 +380,50 @@
 static jobjectArray Class_getDeclaredMethodsUnchecked(JNIEnv* env, jobject javaThis,
                                                       jboolean publicOnly) {
   ScopedFastNativeObjectAccess soa(env);
-  StackHandleScope<5> hs(soa.Self());
+  StackHandleScope<3> hs(soa.Self());
   auto* klass = DecodeClass(soa, javaThis);
-  auto virtual_methods = hs.NewHandle(klass->GetVirtualMethods());
-  auto direct_methods = hs.NewHandle(klass->GetDirectMethods());
   size_t num_methods = 0;
-  if (virtual_methods.Get() != nullptr) {
-    for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
-      auto* m = virtual_methods->GetWithoutChecks(i);
-      auto modifiers = m->GetAccessFlags();
-      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
-          (modifiers & kAccMiranda) == 0) {
-        ++num_methods;
-      }
+  for (auto& m : klass->GetVirtualMethods(sizeof(void*))) {
+    auto modifiers = m.GetAccessFlags();
+    if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+        (modifiers & kAccMiranda) == 0) {
+      ++num_methods;
     }
   }
-  if (direct_methods.Get() != nullptr) {
-    for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
-      auto* m = direct_methods->GetWithoutChecks(i);
-      auto modifiers = m->GetAccessFlags();
-      // Add non-constructor direct/static methods.
-      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
-          (modifiers & kAccConstructor) == 0) {
-        ++num_methods;
-      }
+  for (auto& m : klass->GetDirectMethods(sizeof(void*))) {
+    auto modifiers = m.GetAccessFlags();
+    // Add non-constructor direct/static methods.
+    if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+        (modifiers & kAccConstructor) == 0) {
+      ++num_methods;
     }
   }
   auto ret = hs.NewHandle(mirror::ObjectArray<mirror::Method>::Alloc(
       soa.Self(), mirror::Method::ArrayClass(), num_methods));
   num_methods = 0;
-  if (virtual_methods.Get() != nullptr) {
-    for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
-      auto* m = virtual_methods->GetWithoutChecks(i);
-      auto modifiers = m->GetAccessFlags();
-      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
-          (modifiers & kAccMiranda) == 0) {
-        auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
-        if (method == nullptr) {
-          soa.Self()->AssertPendingException();
-          return nullptr;
-        }
-        ret->SetWithoutChecks<false>(num_methods++, method);
+  for (auto& m : klass->GetVirtualMethods(sizeof(void*))) {
+    auto modifiers = m.GetAccessFlags();
+    if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+        (modifiers & kAccMiranda) == 0) {
+      auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), &m);
+      if (method == nullptr) {
+        soa.Self()->AssertPendingException();
+        return nullptr;
       }
+      ret->SetWithoutChecks<false>(num_methods++, method);
     }
   }
-  if (direct_methods.Get() != nullptr) {
-    for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
-      auto* m = direct_methods->GetWithoutChecks(i);
-      auto modifiers = m->GetAccessFlags();
-      // Add non-constructor direct/static methods.
-      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
-          (modifiers & kAccConstructor) == 0) {
-        auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
-        if (method == nullptr) {
-          soa.Self()->AssertPendingException();
-          return nullptr;
-        }
-        ret->SetWithoutChecks<false>(num_methods++, method);
+  for (auto& m : klass->GetDirectMethods(sizeof(void*))) {
+    auto modifiers = m.GetAccessFlags();
+    // Add non-constructor direct/static methods.
+    if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+        (modifiers & kAccConstructor) == 0) {
+      auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), &m);
+      if (method == nullptr) {
+        soa.Self()->AssertPendingException();
+        return nullptr;
       }
+      ret->SetWithoutChecks<false>(num_methods++, method);
     }
   }
   return soa.AddLocalReference<jobjectArray>(ret.Get());
diff --git a/runtime/native/java_lang_DexCache.cc b/runtime/native/java_lang_DexCache.cc
index b9f8d01..a2d9797 100644
--- a/runtime/native/java_lang_DexCache.cc
+++ b/runtime/native/java_lang_DexCache.cc
@@ -18,6 +18,7 @@
 
 #include "dex_file.h"
 #include "jni_internal.h"
+#include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/object-inl.h"
 #include "scoped_fast_native_object_access.h"
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index 0fd6759..93ba84a 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -16,10 +16,9 @@
 
 #include "java_lang_reflect_Constructor.h"
 
+#include "art_method-inl.h"
 #include "class_linker.h"
 #include "jni_internal.h"
-#include "mirror/art_method.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/method.h"
 #include "mirror/object-inl.h"
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index d6aa9b5..ba898c6 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -21,7 +21,6 @@
 #include "common_throws.h"
 #include "dex_file-inl.h"
 #include "jni_internal.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/field.h"
 #include "reflection-inl.h"
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index c20d832..9533b4d 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -16,10 +16,9 @@
 
 #include "java_lang_reflect_Method.h"
 
+#include "art_method-inl.h"
 #include "class_linker.h"
 #include "jni_internal.h"
-#include "mirror/art_method.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
@@ -37,16 +36,17 @@
 
 static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::ArtMethod* proxy_method = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod);
+  ArtMethod* proxy_method = ArtMethod::FromReflectedMethod(soa, javaMethod);
   CHECK(proxy_method->GetDeclaringClass()->IsProxyClass());
   mirror::Class* proxy_class = proxy_method->GetDeclaringClass();
   int throws_index = -1;
-  size_t num_virt_methods = proxy_class->NumVirtualMethods();
-  for (size_t i = 0; i < num_virt_methods; i++) {
-    if (proxy_class->GetVirtualMethod(i) == proxy_method) {
+  size_t i = 0;
+  for (const auto& m : proxy_class->GetVirtualMethods(sizeof(void*))) {
+    if (&m == proxy_method) {
       throws_index = i;
       break;
     }
+    ++i;
   }
   CHECK_NE(throws_index, -1);
   mirror::ObjectArray<mirror::Class>* declared_exceptions =
diff --git a/runtime/native/scoped_fast_native_object_access.h b/runtime/native/scoped_fast_native_object_access.h
index dfabff5..57b873b 100644
--- a/runtime/native/scoped_fast_native_object_access.h
+++ b/runtime/native/scoped_fast_native_object_access.h
@@ -17,7 +17,7 @@
 #ifndef ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_H_
 #define ART_RUNTIME_NATIVE_SCOPED_FAST_NATIVE_OBJECT_ACCESS_H_
 
-#include "mirror/art_method-inl.h"
+#include "art_method-inl.h"
 #include "scoped_thread_state_change.h"
 
 namespace art {
@@ -31,7 +31,7 @@
     SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE
      : ScopedObjectAccessAlreadyRunnable(env) {
     Locks::mutator_lock_->AssertSharedHeld(Self());
-    DCHECK(Self()->GetManagedStack()->GetTopQuickFrame()->AsMirrorPtr()->IsFastNative());
+    DCHECK((*Self()->GetManagedStack()->GetTopQuickFrame())->IsFastNative());
     // Don't work with raw objects in non-runnable states.
     DCHECK_EQ(Self()->GetState(), kRunnable);
   }
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index 17ebdff..770644c 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -19,7 +19,7 @@
 #include "gc/accounting/card_table-inl.h"
 #include "jni_internal.h"
 #include "mirror/array.h"
-#include "mirror/object.h"
+#include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "scoped_fast_native_object_access.h"
 
diff --git a/runtime/native_bridge_art_interface.cc b/runtime/native_bridge_art_interface.cc
index 0ad560e..46cc5aa 100644
--- a/runtime/native_bridge_art_interface.cc
+++ b/runtime/native_bridge_art_interface.cc
@@ -20,10 +20,10 @@
 
 #include "nativebridge/native_bridge.h"
 
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "dex_file-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "scoped_thread_state_change.h"
 #include "sigchain.h"
@@ -32,29 +32,24 @@
 
 static const char* GetMethodShorty(JNIEnv* env, jmethodID mid) {
   ScopedObjectAccess soa(env);
-  mirror::ArtMethod* m = soa.DecodeMethod(mid);
+  ArtMethod* m = soa.DecodeMethod(mid);
   return m->GetShorty();
 }
 
 static uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz) {
-  if (clazz == nullptr)
+  if (clazz == nullptr) {
     return 0;
+  }
 
   ScopedObjectAccess soa(env);
   mirror::Class* c = soa.Decode<mirror::Class*>(clazz);
 
   uint32_t native_method_count = 0;
-  for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) {
-    mirror::ArtMethod* m = c->GetDirectMethod(i);
-    if (m->IsNative()) {
-      native_method_count++;
-    }
+  for (auto& m : c->GetDirectMethods(sizeof(void*))) {
+    native_method_count += m.IsNative() ? 1u : 0u;
   }
-  for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) {
-    mirror::ArtMethod* m = c->GetVirtualMethod(i);
-    if (m->IsNative()) {
-      native_method_count++;
-    }
+  for (auto& m : c->GetVirtualMethods(sizeof(void*))) {
+    native_method_count += m.IsNative() ? 1u : 0u;
   }
   return native_method_count;
 }
@@ -68,29 +63,27 @@
   mirror::Class* c = soa.Decode<mirror::Class*>(clazz);
 
   uint32_t count = 0;
-  for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) {
-    mirror::ArtMethod* m = c->GetDirectMethod(i);
-    if (m->IsNative()) {
+  for (auto& m : c->GetDirectMethods(sizeof(void*))) {
+    if (m.IsNative()) {
       if (count < method_count) {
-        methods[count].name = m->GetName();
-        methods[count].signature = m->GetShorty();
-        methods[count].fnPtr = m->GetEntryPointFromJni();
+        methods[count].name = m.GetName();
+        methods[count].signature = m.GetShorty();
+        methods[count].fnPtr = m.GetEntryPointFromJni();
         count++;
       } else {
-        LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(m);
+        LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(&m);
       }
     }
   }
-  for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) {
-    mirror::ArtMethod* m = c->GetVirtualMethod(i);
-    if (m->IsNative()) {
+  for (auto& m : c->GetVirtualMethods(sizeof(void*))) {
+    if (m.IsNative()) {
       if (count < method_count) {
-        methods[count].name = m->GetName();
-        methods[count].signature = m->GetShorty();
-        methods[count].fnPtr = m->GetEntryPointFromJni();
+        methods[count].name = m.GetName();
+        methods[count].signature = m.GetShorty();
+        methods[count].fnPtr = m.GetEntryPointFromJni();
         count++;
       } else {
-        LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(m);
+        LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(&m);
       }
     }
   }
diff --git a/runtime/nth_caller_visitor.h b/runtime/nth_caller_visitor.h
index d2d7fa8..7fe3130 100644
--- a/runtime/nth_caller_visitor.h
+++ b/runtime/nth_caller_visitor.h
@@ -17,8 +17,8 @@
 #ifndef ART_RUNTIME_NTH_CALLER_VISITOR_H_
 #define ART_RUNTIME_NTH_CALLER_VISITOR_H_
 
+#include "art_method.h"
 #include "base/mutex.h"
-#include "mirror/art_method.h"
 #include "stack.h"
 
 namespace art {
@@ -34,7 +34,7 @@
         caller(nullptr) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     bool do_count = false;
     if (m == nullptr || m->IsRuntimeMethod()) {
       // Upcall.
@@ -56,7 +56,7 @@
   const size_t n;
   const bool include_runtime_and_upcalls_;
   size_t count;
-  mirror::ArtMethod* caller;
+  ArtMethod* caller;
 };
 
 }  // namespace art
diff --git a/runtime/oat_file-inl.h b/runtime/oat_file-inl.h
index a429c87..6b3b666 100644
--- a/runtime/oat_file-inl.h
+++ b/runtime/oat_file-inl.h
@@ -22,7 +22,7 @@
 namespace art {
 
 inline const OatQuickMethodHeader* OatFile::OatMethod::GetOatQuickMethodHeader() const {
-  const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+  const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode());
   if (code == nullptr) {
     return nullptr;
   }
@@ -39,7 +39,7 @@
 }
 
 inline uint32_t OatFile::OatMethod::GetQuickCodeSize() const {
-  const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+  const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode());
   if (code == nullptr) {
     return 0u;
   }
@@ -55,7 +55,7 @@
 }
 
 inline size_t OatFile::OatMethod::GetFrameSizeInBytes() const {
-  const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+  const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode());
   if (code == nullptr) {
     return 0u;
   }
@@ -63,7 +63,7 @@
 }
 
 inline uint32_t OatFile::OatMethod::GetCoreSpillMask() const {
-  const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+  const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode());
   if (code == nullptr) {
     return 0u;
   }
@@ -71,7 +71,7 @@
 }
 
 inline uint32_t OatFile::OatMethod::GetFpSpillMask() const {
-  const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+  const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode());
   if (code == nullptr) {
     return 0u;
   }
@@ -79,7 +79,7 @@
 }
 
 const uint8_t* OatFile::OatMethod::GetGcMap() const {
-  const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+  const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode());
   if (code == nullptr) {
     return nullptr;
   }
@@ -130,7 +130,7 @@
 }
 
 inline const uint8_t* OatFile::OatMethod::GetMappingTable() const {
-  const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+  const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode());
   if (code == nullptr) {
     return nullptr;
   }
@@ -142,7 +142,7 @@
 }
 
 inline const uint8_t* OatFile::OatMethod::GetVmapTable() const {
-  const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+  const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode());
   if (code == nullptr) {
     return nullptr;
   }
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 63ee4b1..6fda790 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -28,14 +28,13 @@
 #include "android/dlext.h"
 #endif
 
+#include "art_method-inl.h"
 #include "base/bit_vector.h"
 #include "base/stl_util.h"
 #include "base/unix_file/fd_file.h"
 #include "elf_file.h"
 #include "elf_utils.h"
 #include "oat.h"
-#include "mirror/art_method.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class.h"
 #include "mirror/object-inl.h"
 #include "os.h"
@@ -693,7 +692,7 @@
   return OatMethod(oat_file_->Begin(), 0);
 }
 
-void OatFile::OatMethod::LinkMethod(mirror::ArtMethod* method) const {
+void OatFile::OatMethod::LinkMethod(ArtMethod* method) const {
   CHECK(method != nullptr);
   method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
 }
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 12e9f6c..c58b029 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -98,7 +98,7 @@
 
   class OatMethod FINAL {
    public:
-    void LinkMethod(mirror::ArtMethod* method) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+    void LinkMethod(ArtMethod* method) const;
 
     uint32_t GetCodeOffset() const {
       return code_offset_;
diff --git a/runtime/object_lock.cc b/runtime/object_lock.cc
index 749fb5d..f7accc0 100644
--- a/runtime/object_lock.cc
+++ b/runtime/object_lock.cc
@@ -47,7 +47,6 @@
   obj_->NotifyAll(self_);
 }
 
-template class ObjectLock<mirror::ArtMethod>;
 template class ObjectLock<mirror::Class>;
 template class ObjectLock<mirror::Object>;
 
diff --git a/runtime/primitive.h b/runtime/primitive.h
index 0ac5f40..ca42c47 100644
--- a/runtime/primitive.h
+++ b/runtime/primitive.h
@@ -26,7 +26,6 @@
 
 static constexpr size_t kObjectReferenceSize = 4;
 
-
 constexpr size_t ComponentSizeShiftWidth(size_t component_size) {
   return component_size == 1u ? 0u :
       component_size == 2u ? 1u :
diff --git a/runtime/profiler.cc b/runtime/profiler.cc
index b149d4b..87b0d43 100644
--- a/runtime/profiler.cc
+++ b/runtime/profiler.cc
@@ -22,6 +22,7 @@
 
 #include <fstream>
 
+#include "art_method-inl.h"
 #include "base/stl_util.h"
 #include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
@@ -30,7 +31,6 @@
 #include "debugger.h"
 #include "dex_file-inl.h"
 #include "instrumentation.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
 #include "mirror/object_array-inl.h"
@@ -57,7 +57,7 @@
 // Walk through the method within depth of max_depth_ on the Java stack
 class BoundedStackVisitor : public StackVisitor {
  public:
-  BoundedStackVisitor(std::vector<std::pair<mirror::ArtMethod*, uint32_t>>* stack,
+  BoundedStackVisitor(std::vector<std::pair<ArtMethod*, uint32_t>>* stack,
       Thread* thread, uint32_t max_depth)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
       : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
@@ -66,7 +66,7 @@
         depth_(0) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     if (m->IsRuntimeMethod()) {
       return true;
     }
@@ -81,7 +81,7 @@
   }
 
  private:
-  std::vector<std::pair<mirror::ArtMethod*, uint32_t>>* stack_;
+  std::vector<std::pair<ArtMethod*, uint32_t>>* stack_;
   const uint32_t max_depth_;
   uint32_t depth_;
 };
@@ -94,7 +94,7 @@
   const ProfilerOptions profile_options = profiler->GetProfilerOptions();
   switch (profile_options.GetProfileType()) {
     case kProfilerMethod: {
-      mirror::ArtMethod* method = thread->GetCurrentMethod(nullptr);
+      ArtMethod* method = thread->GetCurrentMethod(nullptr);
       if ((false) && method == nullptr) {
         LOG(INFO) << "No current method available";
         std::ostringstream os;
@@ -402,7 +402,7 @@
 
 // Filter out methods the profiler doesn't want to record.
 // We require mutator lock since some statistics will be updated here.
-bool BackgroundMethodSamplingProfiler::ProcessMethod(mirror::ArtMethod* method) {
+bool BackgroundMethodSamplingProfiler::ProcessMethod(ArtMethod* method) {
   if (method == nullptr) {
     profile_table_.NullMethod();
     // Don't record a null method.
@@ -437,7 +437,7 @@
 
 // A method has been hit, record its invocation in the method map.
 // The mutator_lock must be held (shared) when this is called.
-void BackgroundMethodSamplingProfiler::RecordMethod(mirror::ArtMethod* method) {
+void BackgroundMethodSamplingProfiler::RecordMethod(ArtMethod* method) {
   // Add to the profile table unless it is filtered out.
   if (ProcessMethod(method)) {
     profile_table_.Put(method);
@@ -450,7 +450,7 @@
     return;
   }
   // Get the method on top of the stack. We use this method to perform filtering.
-  mirror::ArtMethod* method = stack.front().first;
+  ArtMethod* method = stack.front().first;
   if (ProcessMethod(method)) {
       profile_table_.PutStack(stack);
   }
@@ -466,7 +466,7 @@
 }
 
 // Profile Table.
-// This holds a mapping of mirror::ArtMethod* to a count of how many times a sample
+// This holds a mapping of ArtMethod* to a count of how many times a sample
 // hit it at the top of the stack.
 ProfileSampleResults::ProfileSampleResults(Mutex& lock) : lock_(lock), num_samples_(0),
     num_null_methods_(0),
@@ -484,7 +484,7 @@
 
 // Add a method to the profile table.  If it's the first time the method
 // has been seen, add it with count=1, otherwise increment the count.
-void ProfileSampleResults::Put(mirror::ArtMethod* method) {
+void ProfileSampleResults::Put(ArtMethod* method) {
   MutexLock mu(Thread::Current(), lock_);
   uint32_t index = Hash(method);
   if (table[index] == nullptr) {
@@ -519,7 +519,7 @@
   for (std::vector<InstructionLocation>::const_reverse_iterator iter = stack.rbegin();
        iter != stack.rend(); ++iter) {
     InstructionLocation inst_loc = *iter;
-    mirror::ArtMethod* method = inst_loc.first;
+    ArtMethod* method = inst_loc.first;
     if (method == nullptr) {
       // skip null method
       continue;
@@ -579,7 +579,7 @@
       Map *map = table[i];
       if (map != nullptr) {
         for (const auto &meth_iter : *map) {
-          mirror::ArtMethod *method = meth_iter.first;
+          ArtMethod *method = meth_iter.first;
           std::string method_name = PrettyMethod(method);
 
           const DexFile::CodeItem* codeitem = method->GetCodeItem();
@@ -711,7 +711,7 @@
   previous_.clear();
 }
 
-uint32_t ProfileSampleResults::Hash(mirror::ArtMethod* method) {
+uint32_t ProfileSampleResults::Hash(ArtMethod* method) {
   return (PointerToLowMemUInt32(method) >> 3) % kHashSize;
 }
 
diff --git a/runtime/profiler.h b/runtime/profiler.h
index ae51c87..7611487 100644
--- a/runtime/profiler.h
+++ b/runtime/profiler.h
@@ -36,12 +36,12 @@
 namespace art {
 
 namespace mirror {
-  class ArtMethod;
   class Class;
 }  // namespace mirror
+class ArtMethod;
 class Thread;
 
-typedef std::pair<mirror::ArtMethod*, uint32_t> InstructionLocation;
+typedef std::pair<ArtMethod*, uint32_t> InstructionLocation;
 
 // This class stores the sampled bounded stacks in a trie structure. A path of the trie represents
 // a particular context with the method on top of the stack being a leaf or an internal node of the
@@ -104,7 +104,7 @@
   explicit ProfileSampleResults(Mutex& lock);
   ~ProfileSampleResults();
 
-  void Put(mirror::ArtMethod* method);
+  void Put(ArtMethod* method);
   void PutStack(const std::vector<InstructionLocation>& stack_dump);
   uint32_t Write(std::ostream &os, ProfileDataType type);
   void ReadPrevious(int fd, ProfileDataType type);
@@ -114,14 +114,14 @@
   void BootMethod() { ++num_boot_methods_; }
 
  private:
-  uint32_t Hash(mirror::ArtMethod* method);
+  uint32_t Hash(ArtMethod* method);
   static constexpr int kHashSize = 17;
   Mutex& lock_;                  // Reference to the main profiler lock - we don't need two of them.
   uint32_t num_samples_;         // Total number of samples taken.
   uint32_t num_null_methods_;    // Number of samples where can don't know the method.
   uint32_t num_boot_methods_;    // Number of samples in the boot path.
 
-  typedef std::map<mirror::ArtMethod*, uint32_t> Map;  // Map of method vs its count.
+  typedef std::map<ArtMethod*, uint32_t> Map;  // Map of method vs its count.
   Map *table[kHashSize];
 
   typedef std::set<StackTrieNode*> TrieNodeSet;
@@ -176,9 +176,9 @@
   static void Stop() LOCKS_EXCLUDED(Locks::profiler_lock_, wait_lock_);
   static void Shutdown() LOCKS_EXCLUDED(Locks::profiler_lock_);
 
-  void RecordMethod(mirror::ArtMethod *method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void RecordMethod(ArtMethod *method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void RecordStack(const std::vector<InstructionLocation>& stack) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool ProcessMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  bool ProcessMethod(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   const ProfilerOptions& GetProfilerOptions() const { return options_; }
 
   Barrier& GetBarrier() {
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 93d1f66..f40c0f1 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -52,8 +52,7 @@
     // Builds the method array.
     jsize methods_count = 3;  // Object.equals, Object.hashCode and Object.toString.
     for (mirror::Class* interface : interfaces) {
-      mirror::ObjectArray<mirror::ArtMethod>* virtual_methods = interface->GetVirtualMethods();
-      methods_count += (virtual_methods == nullptr) ? 0 : virtual_methods->GetLength();
+      methods_count += interface->NumVirtualMethods();
     }
     jobjectArray proxyClassMethods = soa.Env()->NewObjectArray(
         methods_count, soa.AddLocalReference<jclass>(mirror::Method::StaticClass()), nullptr);
@@ -61,28 +60,29 @@
 
     jsize array_index = 0;
     // Fill the method array
-    mirror::ArtMethod* method = javaLangObject->FindDeclaredVirtualMethod(
-        "equals", "(Ljava/lang/Object;)Z");
+    ArtMethod* method = javaLangObject->FindDeclaredVirtualMethod(
+        "equals", "(Ljava/lang/Object;)Z", sizeof(void*));
     CHECK(method != nullptr);
     soa.Env()->SetObjectArrayElement(
         proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
             mirror::Method::CreateFromArtMethod(soa.Self(), method)));
-    method = javaLangObject->FindDeclaredVirtualMethod("hashCode", "()I");
+    method = javaLangObject->FindDeclaredVirtualMethod("hashCode", "()I", sizeof(void*));
     CHECK(method != nullptr);
     soa.Env()->SetObjectArrayElement(
         proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
             mirror::Method::CreateFromArtMethod(soa.Self(), method)));
-    method = javaLangObject->FindDeclaredVirtualMethod("toString", "()Ljava/lang/String;");
+    method = javaLangObject->FindDeclaredVirtualMethod(
+        "toString", "()Ljava/lang/String;", sizeof(void*));
     CHECK(method != nullptr);
     soa.Env()->SetObjectArrayElement(
         proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
             mirror::Method::CreateFromArtMethod(soa.Self(), method)));
     // Now adds all interfaces virtual methods.
     for (mirror::Class* interface : interfaces) {
-      for (int32_t i = 0, count = interface->NumVirtualMethods(); i < count; ++i) {
+      for (auto& m : interface->GetVirtualMethods(sizeof(void*))) {
         soa.Env()->SetObjectArrayElement(
             proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
-                mirror::Method::CreateFromArtMethod(soa.Self(), interface->GetVirtualMethod(i))));
+                mirror::Method::CreateFromArtMethod(soa.Self(), &m)));
       }
     }
     CHECK_EQ(array_index, methods_count);
diff --git a/runtime/quick/inline_method_analyser.cc b/runtime/quick/inline_method_analyser.cc
index 1c404ff..99e262e 100644
--- a/runtime/quick/inline_method_analyser.cc
+++ b/runtime/quick/inline_method_analyser.cc
@@ -17,11 +17,11 @@
 #include "inline_method_analyser.h"
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
 #include "dex_instruction.h"
 #include "dex_instruction-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "verifier/method_verifier-inl.h"
@@ -330,8 +330,9 @@
                                                       InlineIGetIPutData* result) {
   mirror::DexCache* dex_cache = verifier->GetDexCache();
   uint32_t method_idx = verifier->GetMethodReference().dex_method_index;
-  mirror::ArtMethod* method = dex_cache->GetResolvedMethod(method_idx);
-  ArtField* field = Runtime::Current()->GetClassLinker()->GetResolvedField(field_idx, dex_cache);
+  auto* cl = Runtime::Current()->GetClassLinker();
+  ArtMethod* method = dex_cache->GetResolvedMethod(method_idx, cl->GetImagePointerSize());
+  ArtField* field = cl->GetResolvedField(field_idx, dex_cache);
   if (method == nullptr || field == nullptr || field->IsStatic()) {
     return false;
   }
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 730759a..8c9782a 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -17,11 +17,11 @@
 #include "quick_exception_handler.h"
 
 #include "arch/context.h"
+#include "art_method-inl.h"
 #include "dex_instruction.h"
 #include "entrypoints/entrypoint_utils.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
 #include "handle_scope-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/throwable.h"
@@ -53,14 +53,14 @@
   }
 
   bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* method = GetMethod();
+    ArtMethod* method = GetMethod();
     exception_handler_->SetHandlerFrameDepth(GetFrameDepth());
     if (method == nullptr) {
       // This is the upcall, we remember the frame and last pc so that we may long jump to them.
       exception_handler_->SetHandlerQuickFramePc(GetCurrentQuickFramePc());
       exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
       uint32_t next_dex_pc;
-      mirror::ArtMethod* next_art_method;
+      ArtMethod* next_art_method;
       bool has_next = GetNextMethodAndDexPc(&next_art_method, &next_dex_pc);
       // Report the method that did the down call as the handler.
       exception_handler_->SetHandlerDexPc(next_dex_pc);
@@ -78,12 +78,11 @@
       DCHECK(method->IsCalleeSaveMethod());
       return true;
     }
-    StackHandleScope<1> hs(self_);
-    return HandleTryItems(hs.NewHandle(method));
+    return HandleTryItems(method);
   }
 
  private:
-  bool HandleTryItems(Handle<mirror::ArtMethod> method)
+  bool HandleTryItems(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     uint32_t dex_pc = DexFile::kDexNoIndex;
     if (!method->IsNative()) {
@@ -91,13 +90,12 @@
     }
     if (dex_pc != DexFile::kDexNoIndex) {
       bool clear_exception = false;
-      StackHandleScope<1> hs(Thread::Current());
+      StackHandleScope<1> hs(self_);
       Handle<mirror::Class> to_find(hs.NewHandle((*exception_)->GetClass()));
-      uint32_t found_dex_pc = mirror::ArtMethod::FindCatchBlock(method, to_find, dex_pc,
-                                                                &clear_exception);
+      uint32_t found_dex_pc = method->FindCatchBlock(to_find, dex_pc, &clear_exception);
       exception_handler_->SetClearException(clear_exception);
       if (found_dex_pc != DexFile::kDexNoIndex) {
-        exception_handler_->SetHandlerMethod(method.Get());
+        exception_handler_->SetHandlerMethod(method);
         exception_handler_->SetHandlerDexPc(found_dex_pc);
         exception_handler_->SetHandlerQuickFramePc(method->ToNativeQuickPc(found_dex_pc));
         exception_handler_->SetHandlerQuickFrame(GetCurrentQuickFrame());
@@ -132,7 +130,7 @@
   visitor.WalkStack(true);
 
   if (kDebugExceptionDelivery) {
-    if (handler_quick_frame_->AsMirrorPtr() == nullptr) {
+    if (*handler_quick_frame_ == nullptr) {
       LOG(INFO) << "Handler is upcall";
     }
     if (handler_method_ != nullptr) {
@@ -171,7 +169,7 @@
 
   bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     exception_handler_->SetHandlerFrameDepth(GetFrameDepth());
-    mirror::ArtMethod* method = GetMethod();
+    ArtMethod* method = GetMethod();
     if (method == nullptr) {
       // This is the upcall, we remember the frame and last pc so that we may long jump to them.
       exception_handler_->SetHandlerQuickFramePc(GetCurrentQuickFramePc());
@@ -191,23 +189,21 @@
     return static_cast<VRegKind>(kinds.at(reg * 2));
   }
 
-  bool HandleDeoptimization(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  bool HandleDeoptimization(ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const DexFile::CodeItem* code_item = m->GetCodeItem();
     CHECK(code_item != nullptr);
     uint16_t num_regs = code_item->registers_size_;
     uint32_t dex_pc = GetDexPc();
-    StackHandleScope<3> hs(self_);  // Dex cache, class loader and method.
+    StackHandleScope<2> hs(self_);  // Dex cache, class loader and method.
     mirror::Class* declaring_class = m->GetDeclaringClass();
     Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
     Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
-    Handle<mirror::ArtMethod> h_method(hs.NewHandle(m));
     verifier::MethodVerifier verifier(self_, h_dex_cache->GetDexFile(), h_dex_cache, h_class_loader,
                                       &m->GetClassDef(), code_item, m->GetDexMethodIndex(),
-                                      h_method, m->GetAccessFlags(), true, true, true, true);
+                                      m, m->GetAccessFlags(), true, true, true, true);
     bool verifier_success = verifier.Verify();
-    CHECK(verifier_success) << PrettyMethod(h_method.Get());
-    ShadowFrame* new_frame = ShadowFrame::CreateDeoptimizedFrame(
-        num_regs, nullptr, h_method.Get(), dex_pc);
+    CHECK(verifier_success) << PrettyMethod(m);
+    ShadowFrame* new_frame = ShadowFrame::CreateDeoptimizedFrame(num_regs, nullptr, m, dex_pc);
     self_->SetShadowFrameUnderConstruction(new_frame);
     const std::vector<int32_t> kinds(verifier.DescribeVRegs(dex_pc));
 
@@ -230,7 +226,7 @@
           // Check IsReferenceVReg in case the compiled GC map doesn't agree with the verifier.
           // We don't want to copy a stale reference into the shadow frame as a reference.
           // b/20736048
-          if (GetVReg(h_method.Get(), reg, kind, &value) && IsReferenceVReg(h_method.Get(), reg)) {
+          if (GetVReg(m, reg, kind, &value) && IsReferenceVReg(m, reg)) {
             new_frame->SetVRegReference(reg, reinterpret_cast<mirror::Object*>(value));
           } else {
             new_frame->SetVReg(reg, kDeadValue);
@@ -241,14 +237,14 @@
           if (GetVRegKind(reg + 1, kinds) == kLongHiVReg) {
             // Treat it as a "long" register pair.
             uint64_t value = 0;
-            if (GetVRegPair(h_method.Get(), reg, kLongLoVReg, kLongHiVReg, &value)) {
+            if (GetVRegPair(m, reg, kLongLoVReg, kLongHiVReg, &value)) {
               new_frame->SetVRegLong(reg, value);
             } else {
               new_frame->SetVRegLong(reg, kLongDeadValue);
             }
           } else {
             uint32_t value = 0;
-            if (GetVReg(h_method.Get(), reg, kind, &value)) {
+            if (GetVReg(m, reg, kind, &value)) {
               new_frame->SetVReg(reg, value);
             } else {
               new_frame->SetVReg(reg, kDeadValue);
@@ -260,7 +256,7 @@
             // Nothing to do: we treated it as a "long" register pair.
           } else {
             uint32_t value = 0;
-            if (GetVReg(h_method.Get(), reg, kind, &value)) {
+            if (GetVReg(m, reg, kind, &value)) {
               new_frame->SetVReg(reg, value);
             } else {
               new_frame->SetVReg(reg, kDeadValue);
@@ -270,7 +266,7 @@
         case kDoubleLoVReg:
           if (GetVRegKind(reg + 1, kinds) == kDoubleHiVReg) {
             uint64_t value = 0;
-            if (GetVRegPair(h_method.Get(), reg, kDoubleLoVReg, kDoubleHiVReg, &value)) {
+            if (GetVRegPair(m, reg, kDoubleLoVReg, kDoubleHiVReg, &value)) {
               // Treat it as a "double" register pair.
               new_frame->SetVRegLong(reg, value);
             } else {
@@ -278,7 +274,7 @@
             }
           } else {
             uint32_t value = 0;
-            if (GetVReg(h_method.Get(), reg, kind, &value)) {
+            if (GetVReg(m, reg, kind, &value)) {
               new_frame->SetVReg(reg, value);
             } else {
               new_frame->SetVReg(reg, kDeadValue);
@@ -290,7 +286,7 @@
             // Nothing to do: we treated it as a "double" register pair.
           } else {
             uint32_t value = 0;
-            if (GetVReg(h_method.Get(), reg, kind, &value)) {
+            if (GetVReg(m, reg, kind, &value)) {
               new_frame->SetVReg(reg, value);
             } else {
               new_frame->SetVReg(reg, kDeadValue);
@@ -299,7 +295,7 @@
           break;
         default:
           uint32_t value = 0;
-          if (GetVReg(h_method.Get(), reg, kind, &value)) {
+          if (GetVReg(m, reg, kind, &value)) {
             new_frame->SetVReg(reg, value);
           } else {
             new_frame->SetVReg(reg, kDeadValue);
diff --git a/runtime/quick_exception_handler.h b/runtime/quick_exception_handler.h
index 7ee4118..8d7cd12 100644
--- a/runtime/quick_exception_handler.h
+++ b/runtime/quick_exception_handler.h
@@ -25,9 +25,9 @@
 namespace art {
 
 namespace mirror {
-class ArtMethod;
 class Throwable;
 }  // namespace mirror
+class ArtMethod;
 class Context;
 class Thread;
 class ShadowFrame;
@@ -48,7 +48,7 @@
   void UpdateInstrumentationStack() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   NO_RETURN void DoLongJump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetHandlerQuickFrame(StackReference<mirror::ArtMethod>* handler_quick_frame) {
+  void SetHandlerQuickFrame(ArtMethod** handler_quick_frame) {
     handler_quick_frame_ = handler_quick_frame;
   }
 
@@ -56,11 +56,11 @@
     handler_quick_frame_pc_ = handler_quick_frame_pc;
   }
 
-  mirror::ArtMethod* GetHandlerMethod() const {
+  ArtMethod* GetHandlerMethod() const {
     return handler_method_;
   }
 
-  void SetHandlerMethod(mirror::ArtMethod* handler_quick_method) {
+  void SetHandlerMethod(ArtMethod* handler_quick_method) {
     handler_method_ = handler_quick_method;
   }
 
@@ -87,11 +87,11 @@
   // Is method tracing active?
   const bool method_tracing_active_;
   // Quick frame with found handler or last frame if no handler found.
-  StackReference<mirror::ArtMethod>* handler_quick_frame_;
+  ArtMethod** handler_quick_frame_;
   // PC to branch to for the handler.
   uintptr_t handler_quick_frame_pc_;
   // The handler method to report to the debugger.
-  mirror::ArtMethod* handler_method_;
+  ArtMethod* handler_method_;
   // The handler's dex PC, zero implies an uncaught exception.
   uint32_t handler_dex_pc_;
   // Should the exception be cleared as the catch block has no move-exception?
diff --git a/runtime/read_barrier.h b/runtime/read_barrier.h
index 52d83a2..aa72e97 100644
--- a/runtime/read_barrier.h
+++ b/runtime/read_barrier.h
@@ -28,12 +28,11 @@
 // which needs to be a C header file for asm_support.h.
 
 namespace art {
-
 namespace mirror {
-  class ArtMethod;
   class Object;
   template<typename MirrorType> class HeapReference;
 }  // namespace mirror
+class ArtMethod;
 
 class ReadBarrier {
  public:
diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc
index 4ffebf2..fae8e72 100644
--- a/runtime/reference_table_test.cc
+++ b/runtime/reference_table_test.cc
@@ -18,7 +18,9 @@
 
 #include "common_runtime_test.h"
 #include "mirror/array-inl.h"
+#include "mirror/class-inl.h"
 #include "mirror/string.h"
+#include "primitive.h"
 #include "scoped_thread_state_change.h"
 #include "thread-inl.h"
 
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index f8c7081..11522d9 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -17,6 +17,7 @@
 #include "reflection-inl.h"
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "class_linker.h"
 #include "common_throws.h"
 #include "dex_file-inl.h"
@@ -24,7 +25,6 @@
 #include "indirect_reference_table-inl.h"
 #include "jni_internal.h"
 #include "mirror/abstract_method.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object_array-inl.h"
 #include "nth_caller_visitor.h"
@@ -213,10 +213,9 @@
   }
 
   bool BuildArgArrayFromObjectArray(mirror::Object* receiver,
-                                    mirror::ObjectArray<mirror::Object>* args,
-                                    Handle<mirror::ArtMethod> h_m)
+                                    mirror::ObjectArray<mirror::Object>* args, ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    const DexFile::TypeList* classes = h_m->GetParameterTypeList();
+    const DexFile::TypeList* classes = m->GetParameterTypeList();
     // Set receiver if non-null (method is not static)
     if (receiver != nullptr) {
       Append(receiver);
@@ -225,11 +224,11 @@
       mirror::Object* arg = args->Get(args_offset);
       if (((shorty_[i] == 'L') && (arg != nullptr)) || ((arg == nullptr && shorty_[i] != 'L'))) {
         mirror::Class* dst_class =
-            h_m->GetClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_, true);
+            m->GetClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_, true);
         if (UNLIKELY(arg == nullptr || !arg->InstanceOf(dst_class))) {
           ThrowIllegalArgumentException(
               StringPrintf("method %s argument %zd has type %s, got %s",
-                  PrettyMethod(h_m.Get(), false).c_str(),
+                  PrettyMethod(m, false).c_str(),
                   args_offset + 1,  // Humans don't count from 0.
                   PrettyDescriptor(dst_class).c_str(),
                   PrettyTypeOf(arg).c_str()).c_str());
@@ -257,7 +256,7 @@
             } else { \
               ThrowIllegalArgumentException(\
                   StringPrintf("method %s argument %zd has type %s, got %s", \
-                      PrettyMethod(h_m.Get(), false).c_str(), \
+                      PrettyMethod(m, false).c_str(), \
                       args_offset + 1, \
                       expected, \
                       PrettyTypeOf(arg).c_str()).c_str()); \
@@ -343,7 +342,7 @@
   std::unique_ptr<uint32_t[]> large_arg_array_;
 };
 
-static void CheckMethodArguments(JavaVMExt* vm, mirror::ArtMethod* m, uint32_t* args)
+static void CheckMethodArguments(JavaVMExt* vm, ArtMethod* m, uint32_t* args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   const DexFile::TypeList* params = m->GetParameterTypeList();
   if (params == nullptr) {
@@ -356,16 +355,14 @@
     offset = 1;
   }
   // TODO: If args contain object references, it may cause problems.
-  Thread* self = Thread::Current();
-  StackHandleScope<1> hs(self);
-  Handle<mirror::ArtMethod> h_m(hs.NewHandle(m));
+  Thread* const self = Thread::Current();
   for (uint32_t i = 0; i < num_params; i++) {
     uint16_t type_idx = params->GetTypeItem(i).type_idx_;
-    mirror::Class* param_type = h_m->GetClassFromTypeIndex(type_idx, true);
+    mirror::Class* param_type = m->GetClassFromTypeIndex(type_idx, true);
     if (param_type == nullptr) {
       CHECK(self->IsExceptionPending());
       LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: "
-          << h_m->GetTypeDescriptorFromTypeIdx(type_idx) << "\n"
+          << m->GetTypeDescriptorFromTypeIdx(type_idx) << "\n"
           << self->GetException()->Dump();
       self->ClearException();
       ++error_count;
@@ -378,7 +375,7 @@
       if (argument != nullptr && !argument->InstanceOf(param_type)) {
         LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of "
                    << PrettyTypeOf(argument) << " as argument " << (i + 1)
-                   << " to " << PrettyMethod(h_m.Get());
+                   << " to " << PrettyMethod(m);
         ++error_count;
       }
     } else if (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble()) {
@@ -388,25 +385,25 @@
       if (param_type->IsPrimitiveBoolean()) {
         if (arg != JNI_TRUE && arg != JNI_FALSE) {
           LOG(ERROR) << "JNI ERROR (app bug): expected jboolean (0/1) but got value of "
-              << arg << " as argument " << (i + 1) << " to " << PrettyMethod(h_m.Get());
+              << arg << " as argument " << (i + 1) << " to " << PrettyMethod(m);
           ++error_count;
         }
       } else if (param_type->IsPrimitiveByte()) {
         if (arg < -128 || arg > 127) {
           LOG(ERROR) << "JNI ERROR (app bug): expected jbyte but got value of "
-              << arg << " as argument " << (i + 1) << " to " << PrettyMethod(h_m.Get());
+              << arg << " as argument " << (i + 1) << " to " << PrettyMethod(m);
           ++error_count;
         }
       } else if (param_type->IsPrimitiveChar()) {
         if (args[i + offset] > 0xFFFF) {
           LOG(ERROR) << "JNI ERROR (app bug): expected jchar but got value of "
-              << arg << " as argument " << (i + 1) << " to " << PrettyMethod(h_m.Get());
+              << arg << " as argument " << (i + 1) << " to " << PrettyMethod(m);
           ++error_count;
         }
       } else if (param_type->IsPrimitiveShort()) {
         if (arg < -32768 || arg > 0x7FFF) {
           LOG(ERROR) << "JNI ERROR (app bug): expected jshort but got value of "
-              << arg << " as argument " << (i + 1) << " to " << PrettyMethod(h_m.Get());
+              << arg << " as argument " << (i + 1) << " to " << PrettyMethod(m);
           ++error_count;
         }
       }
@@ -416,24 +413,23 @@
     // TODO: pass the JNI function name (such as "CallVoidMethodV") through so we can call JniAbort
     // with an argument.
     vm->JniAbortF(nullptr, "bad arguments passed to %s (see above for details)",
-                  PrettyMethod(h_m.Get()).c_str());
+                  PrettyMethod(m).c_str());
   }
 }
 
-static mirror::ArtMethod* FindVirtualMethod(mirror::Object* receiver,
-                                            mirror::ArtMethod* method)
+static ArtMethod* FindVirtualMethod(mirror::Object* receiver, ArtMethod* method)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method);
+  return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method, sizeof(void*));
 }
 
 
 static void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa,
-                               mirror::ArtMethod* method, ArgArray* arg_array, JValue* result,
+                               ArtMethod* method, ArgArray* arg_array, JValue* result,
                                const char* shorty)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   uint32_t* args = arg_array->GetArray();
   if (UNLIKELY(soa.Env()->check_jni)) {
-    CheckMethodArguments(soa.Vm(), method, args);
+    CheckMethodArguments(soa.Vm(), method->GetInterfaceMethodIfProxy(sizeof(void*)), args);
   }
   method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty);
 }
@@ -449,7 +445,7 @@
     return JValue();
   }
 
-  mirror::ArtMethod* method = soa.DecodeMethod(mid);
+  ArtMethod* method = soa.DecodeMethod(mid);
   bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
   if (is_string_init) {
     // Replace calls to String.<init> with equivalent StringFactory call.
@@ -479,7 +475,7 @@
     return JValue();
   }
 
-  mirror::ArtMethod* method = soa.DecodeMethod(mid);
+  ArtMethod* method = soa.DecodeMethod(mid);
   bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
   if (is_string_init) {
     // Replace calls to String.<init> with equivalent StringFactory call.
@@ -510,7 +506,7 @@
   }
 
   mirror::Object* receiver = soa.Decode<mirror::Object*>(obj);
-  mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
+  ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
   bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
   if (is_string_init) {
     // Replace calls to String.<init> with equivalent StringFactory call.
@@ -541,7 +537,7 @@
   }
 
   mirror::Object* receiver = soa.Decode<mirror::Object*>(obj);
-  mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
+  ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
   bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
   if (is_string_init) {
     // Replace calls to String.<init> with equivalent StringFactory call.
@@ -574,7 +570,7 @@
 
   auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(javaMethod);
   const bool accessible = abstract_method->IsAccessible();
-  mirror::ArtMethod* m = abstract_method->GetArtMethod();
+  ArtMethod* m = abstract_method->GetArtMethod();
 
   mirror::Class* declaring_class = m->GetDeclaringClass();
   if (UNLIKELY(!declaring_class->IsInitialized())) {
@@ -601,13 +597,14 @@
       }
 
       // Find the actual implementation of the virtual method.
-      m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m);
+      m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m, sizeof(void*));
     }
   }
 
   // Get our arrays of arguments and their types, and check they're the same size.
   auto* objects = soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs);
-  const DexFile::TypeList* classes = m->GetParameterTypeList();
+  auto* np_method = m->GetInterfaceMethodIfProxy(sizeof(void*));
+  const DexFile::TypeList* classes = np_method->GetParameterTypeList();
   uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size();
   uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0;
   if (arg_count != classes_size) {
@@ -633,11 +630,9 @@
   // Invoke the method.
   JValue result;
   uint32_t shorty_len = 0;
-  const char* shorty = m->GetShorty(&shorty_len);
+  const char* shorty = np_method->GetShorty(&shorty_len);
   ArgArray arg_array(shorty, shorty_len);
-  StackHandleScope<1> hs(soa.Self());
-  Handle<mirror::ArtMethod> h_m(hs.NewHandle(m));
-  if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, h_m)) {
+  if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, np_method)) {
     CHECK(soa.Self()->IsExceptionPending());
     return nullptr;
   }
diff --git a/runtime/reflection.h b/runtime/reflection.h
index df3b9d3..825a721 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -23,11 +23,11 @@
 
 namespace art {
 namespace mirror {
-  class ArtMethod;
   class Class;
   class Object;
 }  // namespace mirror
 class ArtField;
+class ArtMethod;
 union JValue;
 class ScopedObjectAccessAlreadyRunnable;
 class ShadowFrame;
diff --git a/runtime/reflection_test.cc b/runtime/reflection_test.cc
index 36e444a..6f17e7d 100644
--- a/runtime/reflection_test.cc
+++ b/runtime/reflection_test.cc
@@ -20,8 +20,8 @@
 #include <limits.h>
 #include "ScopedLocalRef.h"
 
+#include "art_method-inl.h"
 #include "common_compiler_test.h"
-#include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 
 namespace art {
@@ -81,7 +81,7 @@
     return soa.AddLocalReference<jclass>(c);
   }
 
-  void ReflectionTestMakeExecutable(mirror::ArtMethod** method,
+  void ReflectionTestMakeExecutable(ArtMethod** method,
                                     mirror::Object** receiver,
                                     bool is_static, const char* method_name,
                                     const char* method_signature)
@@ -107,8 +107,8 @@
                                                 class_loader);
     CHECK(c != nullptr);
 
-    *method = is_static ? c->FindDirectMethod(method_name, method_signature)
-                        : c->FindVirtualMethod(method_name, method_signature);
+    *method = is_static ? c->FindDirectMethod(method_name, method_signature, sizeof(void*))
+                        : c->FindVirtualMethod(method_name, method_signature, sizeof(void*));
     CHECK(method != nullptr);
 
     if (is_static) {
@@ -130,7 +130,7 @@
 
   void InvokeNopMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "nop", "()V");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -139,7 +139,7 @@
 
   void InvokeIdentityByteMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "identity", "(B)B");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -164,7 +164,7 @@
 
   void InvokeIdentityIntMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "identity", "(I)I");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -189,7 +189,7 @@
 
   void InvokeIdentityDoubleMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "identity", "(D)D");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -214,7 +214,7 @@
 
   void InvokeSumIntIntMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(II)I");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -243,7 +243,7 @@
 
   void InvokeSumIntIntIntMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(III)I");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -282,7 +282,7 @@
 
   void InvokeSumIntIntIntIntMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(IIII)I");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -326,7 +326,7 @@
 
   void InvokeSumIntIntIntIntIntMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(IIIII)I");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -375,7 +375,7 @@
 
   void InvokeSumDoubleDoubleMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DD)D");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -409,7 +409,7 @@
 
   void InvokeSumDoubleDoubleDoubleMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DDD)D");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -436,7 +436,7 @@
 
   void InvokeSumDoubleDoubleDoubleDoubleMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DDDD)D");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -466,7 +466,7 @@
 
   void InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(bool is_static) {
     ScopedObjectAccess soa(env_);
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     mirror::Object* receiver;
     ReflectionTestMakeExecutable(&method, &receiver, is_static, "sum", "(DDDDD)D");
     ScopedLocalRef<jobject> receiver_ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
@@ -515,7 +515,7 @@
   mirror::Class* klass = class_linker_->FindClass(soa.Self(), "LMain;", class_loader);
   ASSERT_TRUE(klass != nullptr);
 
-  mirror::ArtMethod* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
+  ArtMethod* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V", sizeof(void*));
   ASSERT_TRUE(method != nullptr);
 
   // Start runtime.
diff --git a/runtime/runtime-inl.h b/runtime/runtime-inl.h
index a82bc85..68d5ad2 100644
--- a/runtime/runtime-inl.h
+++ b/runtime/runtime-inl.h
@@ -19,7 +19,7 @@
 
 #include "runtime.h"
 
-#include "mirror/art_method.h"
+#include "art_method.h"
 #include "read_barrier-inl.h"
 
 namespace art {
@@ -34,52 +34,46 @@
   return obj;
 }
 
-inline QuickMethodFrameInfo Runtime::GetRuntimeMethodFrameInfo(mirror::ArtMethod* method) {
+inline QuickMethodFrameInfo Runtime::GetRuntimeMethodFrameInfo(ArtMethod* method) {
   DCHECK(method != nullptr);
   // Cannot be imt-conflict-method or resolution-method.
-  DCHECK(method != GetImtConflictMethod());
-  DCHECK(method != GetResolutionMethod());
+  DCHECK_NE(method, GetImtConflictMethod());
+  DCHECK_NE(method, GetResolutionMethod());
   // Don't use GetCalleeSaveMethod(), some tests don't set all callee save methods.
   if (method == GetCalleeSaveMethodUnchecked(Runtime::kRefsAndArgs)) {
     return GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
   } else if (method == GetCalleeSaveMethodUnchecked(Runtime::kSaveAll)) {
     return GetCalleeSaveMethodFrameInfo(Runtime::kSaveAll);
   } else {
-    DCHECK(method == GetCalleeSaveMethodUnchecked(Runtime::kRefsOnly));
+    DCHECK_EQ(method, GetCalleeSaveMethodUnchecked(Runtime::kRefsOnly));
     return GetCalleeSaveMethodFrameInfo(Runtime::kRefsOnly);
   }
 }
 
-inline mirror::ArtMethod* Runtime::GetResolutionMethod() {
+inline ArtMethod* Runtime::GetResolutionMethod() {
   CHECK(HasResolutionMethod());
-  return resolution_method_.Read();
+  return resolution_method_;
 }
 
-inline mirror::ArtMethod* Runtime::GetImtConflictMethod() {
+inline ArtMethod* Runtime::GetImtConflictMethod() {
   CHECK(HasImtConflictMethod());
-  return imt_conflict_method_.Read();
+  return imt_conflict_method_;
 }
 
-inline mirror::ArtMethod* Runtime::GetImtUnimplementedMethod() {
-  CHECK(!imt_unimplemented_method_.IsNull());
-  return imt_unimplemented_method_.Read();
+inline ArtMethod* Runtime::GetImtUnimplementedMethod() {
+  CHECK(imt_unimplemented_method_ != nullptr);
+  return imt_unimplemented_method_;
 }
 
-inline mirror::ObjectArray<mirror::ArtMethod>* Runtime::GetDefaultImt()
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  CHECK(HasDefaultImt());
-  return default_imt_.Read();
-}
-
-inline mirror::ArtMethod* Runtime::GetCalleeSaveMethod(CalleeSaveType type)
+inline ArtMethod* Runtime::GetCalleeSaveMethod(CalleeSaveType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   DCHECK(HasCalleeSaveMethod(type));
-  return callee_save_methods_[type].Read();
+  return GetCalleeSaveMethodUnchecked(type);
 }
 
-inline mirror::ArtMethod* Runtime::GetCalleeSaveMethodUnchecked(CalleeSaveType type)
+inline ArtMethod* Runtime::GetCalleeSaveMethodUnchecked(CalleeSaveType type)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return callee_save_methods_[type].Read();
+  return reinterpret_cast<ArtMethod*>(callee_save_methods_[type]);
 }
 
 }  // namespace art
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 2618661..81846df 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -49,6 +49,7 @@
 #include "arch/x86_64/quick_method_frame_info_x86_64.h"
 #include "arch/x86_64/registers_x86_64.h"
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "asm_support.h"
 #include "atomic.h"
 #include "base/arena_allocator.h"
@@ -73,7 +74,6 @@
 #include "jni_internal.h"
 #include "linear_alloc.h"
 #include "mirror/array.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/field.h"
@@ -189,6 +189,7 @@
       is_native_bridge_loaded_(false),
       zygote_max_failed_boots_(0) {
   CheckAsmSupportOffsetsAndSizes();
+  std::fill(callee_save_methods_, callee_save_methods_ + arraysize(callee_save_methods_), 0u);
 }
 
 Runtime::~Runtime() {
@@ -425,20 +426,20 @@
 
   ScopedObjectAccess soa(Thread::Current());
   ClassLinker* cl = Runtime::Current()->GetClassLinker();
+  auto pointer_size = cl->GetImagePointerSize();
 
   StackHandleScope<2> hs(soa.Self());
   Handle<mirror::Class> class_loader_class(
       hs.NewHandle(soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader)));
   CHECK(cl->EnsureInitialized(soa.Self(), class_loader_class, true, true));
 
-  mirror::ArtMethod* getSystemClassLoader =
-      class_loader_class->FindDirectMethod("getSystemClassLoader", "()Ljava/lang/ClassLoader;");
+  ArtMethod* getSystemClassLoader = class_loader_class->FindDirectMethod(
+      "getSystemClassLoader", "()Ljava/lang/ClassLoader;", pointer_size);
   CHECK(getSystemClassLoader != nullptr);
 
   JValue result = InvokeWithJValues(soa, nullptr, soa.EncodeMethod(getSystemClassLoader), nullptr);
   JNIEnv* env = soa.Self()->GetJniEnv();
-  ScopedLocalRef<jobject> system_class_loader(env,
-                                              soa.AddLocalReference<jobject>(result.GetL()));
+  ScopedLocalRef<jobject> system_class_loader(env, soa.AddLocalReference<jobject>(result.GetL()));
   CHECK(system_class_loader.get() != nullptr);
 
   soa.Self()->SetClassLoaderOverride(system_class_loader.get());
@@ -867,18 +868,17 @@
   }
 
   jit_options_.reset(jit::JitOptions::CreateFromRuntimeArguments(runtime_options));
-  bool use_jit = jit_options_->UseJIT();
   if (IsAotCompiler()) {
     // If we are already the compiler at this point, we must be dex2oat. Don't create the jit in
     // this case.
     // If runtime_options doesn't have UseJIT set to true then CreateFromRuntimeArguments returns
     // null and we don't create the jit.
-    use_jit = false;
+    jit_options_->SetUseJIT(false);
   }
 
   // Use MemMap arena pool for jit, malloc otherwise. Malloc arenas are faster to allocate but
   // can't be trimmed as easily.
-  const bool use_malloc = !use_jit;
+  const bool use_malloc = IsAotCompiler();
   arena_pool_.reset(new ArenaPool(use_malloc, false));
   if (IsCompiler() && Is64BitInstructionSet(kRuntimeISA)) {
     // 4gb, no malloc. Explanation in header.
@@ -1089,6 +1089,7 @@
   }
 
   VLOG(startup) << "Runtime::Init exiting";
+
   return true;
 }
 
@@ -1311,7 +1312,6 @@
 void Runtime::VisitConstantRoots(RootVisitor* visitor) {
   // Visit the classes held as static in mirror classes, these can be visited concurrently and only
   // need to be visited once per GC since they never change.
-  mirror::ArtMethod::VisitRoots(visitor);
   mirror::Class::VisitRoots(visitor);
   mirror::Constructor::VisitRoots(visitor);
   mirror::Reference::VisitRoots(visitor);
@@ -1350,17 +1350,9 @@
   java_vm_->VisitRoots(visitor);
   sentinel_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
   pre_allocated_OutOfMemoryError_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
-  resolution_method_.VisitRoot(visitor, RootInfo(kRootVMInternal));
   pre_allocated_NoClassDefFoundError_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
-  imt_conflict_method_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
-  imt_unimplemented_method_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
-  default_imt_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
-  for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
-    callee_save_methods_[i].VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
-  }
   verifier::MethodVerifier::VisitStaticRoots(visitor);
   VisitTransactionRoots(visitor);
-  instrumentation_.VisitRoots(visitor);
 }
 
 void Runtime::VisitNonConcurrentRoots(RootVisitor* visitor) {
@@ -1399,73 +1391,43 @@
   }
 }
 
-mirror::ObjectArray<mirror::ArtMethod>* Runtime::CreateDefaultImt(ClassLinker* cl) {
-  Thread* self = Thread::Current();
-  StackHandleScope<1> hs(self);
-  Handle<mirror::ObjectArray<mirror::ArtMethod>> imtable(
-      hs.NewHandle(cl->AllocArtMethodArray(self, 64)));
-  mirror::ArtMethod* imt_conflict_method = Runtime::Current()->GetImtConflictMethod();
-  for (size_t i = 0; i < static_cast<size_t>(imtable->GetLength()); i++) {
-    imtable->Set<false>(i, imt_conflict_method);
-  }
-  return imtable.Get();
-}
-
-mirror::ArtMethod* Runtime::CreateImtConflictMethod() {
-  Thread* self = Thread::Current();
-  Runtime* runtime = Runtime::Current();
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  StackHandleScope<1> hs(self);
-  Handle<mirror::ArtMethod> method(hs.NewHandle(class_linker->AllocArtMethod(self)));
-  method->SetDeclaringClass(mirror::ArtMethod::GetJavaLangReflectArtMethod());
-  // TODO: use a special method for imt conflict method saves.
-  method->SetDexMethodIndex(DexFile::kDexNoIndex);
+ArtMethod* Runtime::CreateImtConflictMethod() {
+  auto* method = Runtime::Current()->GetClassLinker()->CreateRuntimeMethod();
   // When compiling, the code pointer will get set later when the image is loaded.
-  if (runtime->IsAotCompiler()) {
+  if (IsAotCompiler()) {
     size_t pointer_size = GetInstructionSetPointerSize(instruction_set_);
     method->SetEntryPointFromQuickCompiledCodePtrSize(nullptr, pointer_size);
   } else {
     method->SetEntryPointFromQuickCompiledCode(GetQuickImtConflictStub());
   }
-  return method.Get();
+  return method;
 }
 
-void Runtime::SetImtConflictMethod(mirror::ArtMethod* method) {
-  imt_conflict_method_ = GcRoot<mirror::ArtMethod>(method);
+void Runtime::SetImtConflictMethod(ArtMethod* method) {
+  CHECK(method != nullptr);
+  CHECK(method->IsRuntimeMethod());
+  imt_conflict_method_ = method;
 }
 
-mirror::ArtMethod* Runtime::CreateResolutionMethod() {
-  Thread* self = Thread::Current();
-  Runtime* runtime = Runtime::Current();
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  StackHandleScope<1> hs(self);
-  Handle<mirror::ArtMethod> method(hs.NewHandle(class_linker->AllocArtMethod(self)));
-  method->SetDeclaringClass(mirror::ArtMethod::GetJavaLangReflectArtMethod());
-  // TODO: use a special method for resolution method saves
-  method->SetDexMethodIndex(DexFile::kDexNoIndex);
+ArtMethod* Runtime::CreateResolutionMethod() {
+  auto* method = Runtime::Current()->GetClassLinker()->CreateRuntimeMethod();
   // When compiling, the code pointer will get set later when the image is loaded.
-  if (runtime->IsAotCompiler()) {
+  if (IsAotCompiler()) {
     size_t pointer_size = GetInstructionSetPointerSize(instruction_set_);
     method->SetEntryPointFromQuickCompiledCodePtrSize(nullptr, pointer_size);
   } else {
     method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionStub());
   }
-  return method.Get();
+  return method;
 }
 
-mirror::ArtMethod* Runtime::CreateCalleeSaveMethod() {
-  Thread* self = Thread::Current();
-  Runtime* runtime = Runtime::Current();
-  ClassLinker* class_linker = runtime->GetClassLinker();
-  StackHandleScope<1> hs(self);
-  Handle<mirror::ArtMethod> method(hs.NewHandle(class_linker->AllocArtMethod(self)));
-  method->SetDeclaringClass(mirror::ArtMethod::GetJavaLangReflectArtMethod());
-  // TODO: use a special method for callee saves
-  method->SetDexMethodIndex(DexFile::kDexNoIndex);
+ArtMethod* Runtime::CreateCalleeSaveMethod() {
+  auto* method = Runtime::Current()->GetClassLinker()->CreateRuntimeMethod();
   size_t pointer_size = GetInstructionSetPointerSize(instruction_set_);
   method->SetEntryPointFromQuickCompiledCodePtrSize(nullptr, pointer_size);
   DCHECK_NE(instruction_set_, kNone);
-  return method.Get();
+  DCHECK(method->IsRuntimeMethod());
+  return method;
 }
 
 void Runtime::DisallowNewSystemWeaks() {
@@ -1525,15 +1487,16 @@
   }
 }
 
-void Runtime::SetCalleeSaveMethod(mirror::ArtMethod* method, CalleeSaveType type) {
+void Runtime::SetCalleeSaveMethod(ArtMethod* method, CalleeSaveType type) {
   DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType));
-  callee_save_methods_[type] = GcRoot<mirror::ArtMethod>(method);
+  CHECK(method != nullptr);
+  callee_save_methods_[type] = reinterpret_cast<uintptr_t>(method);
 }
 
 void Runtime::StartProfiler(const char* profile_output_filename) {
   profile_output_filename_ = profile_output_filename;
   profiler_started_ =
-    BackgroundMethodSamplingProfiler::Start(profile_output_filename_, profiler_options_);
+      BackgroundMethodSamplingProfiler::Start(profile_output_filename_, profiler_options_);
 }
 
 // Transaction support.
@@ -1550,7 +1513,6 @@
   preinitialization_transaction_ = nullptr;
 }
 
-
 bool Runtime::IsTransactionAborted() const {
   if (!IsActiveTransaction()) {
     return false;
@@ -1709,4 +1671,16 @@
   return IsCompiler() && compiler_callbacks_->IsBootImage();
 }
 
+void Runtime::SetResolutionMethod(ArtMethod* method) {
+  CHECK(method != nullptr);
+  CHECK(method->IsRuntimeMethod()) << method;
+  resolution_method_ = method;
+}
+
+void Runtime::SetImtUnimplementedMethod(ArtMethod* method) {
+  CHECK(method != nullptr);
+  CHECK(method->IsRuntimeMethod());
+  imt_unimplemented_method_ = method;
+}
+
 }  // namespace art
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 348d5c6..f6f9725 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -41,10 +41,6 @@
 
 namespace art {
 
-class ArenaPool;
-class CompilerCallbacks;
-class LinearAlloc;
-
 namespace gc {
   class Heap;
   namespace collector {
@@ -58,7 +54,6 @@
 }  // namespace jit
 
 namespace mirror {
-  class ArtMethod;
   class ClassLoader;
   class Array;
   template<class T> class ObjectArray;
@@ -70,11 +65,15 @@
 namespace verifier {
   class MethodVerifier;
 }  // namespace verifier
+class ArenaPool;
+class ArtMethod;
 class ClassLinker;
 class Closure;
+class CompilerCallbacks;
 class DexFile;
 class InternTable;
 class JavaVMExt;
+class LinearAlloc;
 class MonitorList;
 class MonitorPool;
 class NullPointerHandler;
@@ -342,47 +341,28 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns a special method that calls into a trampoline for runtime method resolution
-  mirror::ArtMethod* GetResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* GetResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool HasResolutionMethod() const {
-    return !resolution_method_.IsNull();
+    return resolution_method_ != nullptr;
   }
 
-  void SetResolutionMethod(mirror::ArtMethod* method) {
-    resolution_method_ = GcRoot<mirror::ArtMethod>(method);
-  }
+  void SetResolutionMethod(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtMethod* CreateResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* CreateResolutionMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns a special method that calls into a trampoline for runtime imt conflicts.
-  mirror::ArtMethod* GetImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  mirror::ArtMethod* GetImtUnimplementedMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* GetImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* GetImtUnimplementedMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool HasImtConflictMethod() const {
-    return !imt_conflict_method_.IsNull();
+    return imt_conflict_method_ != nullptr;
   }
 
-  void SetImtConflictMethod(mirror::ArtMethod* method);
-  void SetImtUnimplementedMethod(mirror::ArtMethod* method) {
-    imt_unimplemented_method_ = GcRoot<mirror::ArtMethod>(method);
-  }
+  void SetImtConflictMethod(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetImtUnimplementedMethod(ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtMethod* CreateImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  // Returns an imt with every entry set to conflict, used as default imt for all classes.
-  mirror::ObjectArray<mirror::ArtMethod>* GetDefaultImt()
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  bool HasDefaultImt() const {
-    return !default_imt_.IsNull();
-  }
-
-  void SetDefaultImt(mirror::ObjectArray<mirror::ArtMethod>* imt) {
-    default_imt_ = GcRoot<mirror::ObjectArray<mirror::ArtMethod>>(imt);
-  }
-
-  mirror::ObjectArray<mirror::ArtMethod>* CreateDefaultImt(ClassLinker* cl)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* CreateImtConflictMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns a special method that describes all callee saves being spilled to the stack.
   enum CalleeSaveType {
@@ -393,20 +373,20 @@
   };
 
   bool HasCalleeSaveMethod(CalleeSaveType type) const {
-    return !callee_save_methods_[type].IsNull();
+    return callee_save_methods_[type] != 0u;
   }
 
-  mirror::ArtMethod* GetCalleeSaveMethod(CalleeSaveType type)
+  ArtMethod* GetCalleeSaveMethod(CalleeSaveType type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtMethod* GetCalleeSaveMethodUnchecked(CalleeSaveType type)
+  ArtMethod* GetCalleeSaveMethodUnchecked(CalleeSaveType type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   QuickMethodFrameInfo GetCalleeSaveMethodFrameInfo(CalleeSaveType type) const {
     return callee_save_method_frame_infos_[type];
   }
 
-  QuickMethodFrameInfo GetRuntimeMethodFrameInfo(mirror::ArtMethod* method)
+  QuickMethodFrameInfo GetRuntimeMethodFrameInfo(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static size_t GetCalleeSaveMethodOffset(CalleeSaveType type) {
@@ -419,9 +399,9 @@
 
   void SetInstructionSet(InstructionSet instruction_set);
 
-  void SetCalleeSaveMethod(mirror::ArtMethod* method, CalleeSaveType type);
+  void SetCalleeSaveMethod(ArtMethod* method, CalleeSaveType type);
 
-  mirror::ArtMethod* CreateCalleeSaveMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* CreateCalleeSaveMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   int32_t GetStat(int kind);
 
@@ -588,15 +568,15 @@
   static constexpr int kProfileForground = 0;
   static constexpr int kProfileBackgrouud = 1;
 
-  GcRoot<mirror::ArtMethod> callee_save_methods_[kLastCalleeSaveType];
+  // 64 bit so that we can share the same asm offsets for both 32 and 64 bits.
+  uint64_t callee_save_methods_[kLastCalleeSaveType];
   GcRoot<mirror::Throwable> pre_allocated_OutOfMemoryError_;
   GcRoot<mirror::Throwable> pre_allocated_NoClassDefFoundError_;
-  GcRoot<mirror::ArtMethod> resolution_method_;
-  GcRoot<mirror::ArtMethod> imt_conflict_method_;
+  ArtMethod* resolution_method_;
+  ArtMethod* imt_conflict_method_;
   // Unresolved method has the same behavior as the conflict method, it is used by the class linker
   // for differentiating between unfilled imt slots vs conflict slots in superclasses.
-  GcRoot<mirror::ArtMethod> imt_unimplemented_method_;
-  GcRoot<mirror::ObjectArray<mirror::ArtMethod>> default_imt_;
+  ArtMethod* imt_unimplemented_method_;
 
   // Special sentinel object used to invalid conditions in JNI (cleared weak references) and
   // JDWP (invalid references).
diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h
index 60ed55a..1cc2df6 100644
--- a/runtime/scoped_thread_state_change.h
+++ b/runtime/scoped_thread_state_change.h
@@ -158,20 +158,15 @@
     return reinterpret_cast<jfieldID>(field);
   }
 
-  mirror::ArtMethod* DecodeMethod(jmethodID mid) const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ArtMethod* DecodeMethod(jmethodID mid) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Locks::mutator_lock_->AssertSharedHeld(Self());
     DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
-    CHECK(!kMovingMethods);
-    mirror::ArtMethod* method = reinterpret_cast<mirror::ArtMethod*>(mid);
-    return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(&method);
+    return reinterpret_cast<ArtMethod*>(mid);
   }
 
-  jmethodID EncodeMethod(mirror::ArtMethod* method) const
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  jmethodID EncodeMethod(ArtMethod* method) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Locks::mutator_lock_->AssertSharedHeld(Self());
     DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
-    CHECK(!kMovingMethods);
     return reinterpret_cast<jmethodID>(method);
   }
 
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 09b56a1..4110887 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -17,13 +17,15 @@
 #include "stack.h"
 
 #include "arch/context.h"
+#include "art_method-inl.h"
 #include "base/hex_dump.h"
 #include "entrypoints/entrypoint_utils-inl.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
 #include "gc_map.h"
-#include "mirror/art_method-inl.h"
+#include "gc/space/image_space.h"
+#include "gc/space/space-inl.h"
+#include "linear_alloc.h"
 #include "mirror/class-inl.h"
-#include "mirror/object.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "quick/quick_method_frame_info.h"
@@ -35,8 +37,10 @@
 
 namespace art {
 
+static constexpr bool kDebugStackWalk = false;
+
 mirror::Object* ShadowFrame::GetThisObject() const {
-  mirror::ArtMethod* m = GetMethod();
+  ArtMethod* m = GetMethod();
   if (m->IsStatic()) {
     return nullptr;
   } else if (m->IsNative()) {
@@ -50,7 +54,7 @@
 }
 
 mirror::Object* ShadowFrame::GetThisObject(uint16_t num_ins) const {
-  mirror::ArtMethod* m = GetMethod();
+  ArtMethod* m = GetMethod();
   if (m->IsStatic()) {
     return nullptr;
   } else {
@@ -105,8 +109,8 @@
   DCHECK(thread == Thread::Current() || thread->IsSuspended()) << *thread;
 }
 
-InlineInfo StackVisitor::GetCurrentInlineInfo() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ArtMethod* outer_method = GetCurrentQuickFrame()->AsMirrorPtr();
+InlineInfo StackVisitor::GetCurrentInlineInfo() const {
+  ArtMethod* outer_method = *GetCurrentQuickFrame();
   uint32_t native_pc_offset = outer_method->NativeQuickPcOffset(cur_quick_frame_pc_);
   CodeInfo code_info = outer_method->GetOptimizedCodeInfo();
   StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
@@ -114,7 +118,7 @@
   return code_info.GetInlineInfoOf(stack_map);
 }
 
-mirror::ArtMethod* StackVisitor::GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ArtMethod* StackVisitor::GetMethod() const {
   if (cur_shadow_frame_ != nullptr) {
     return cur_shadow_frame_->GetMethod();
   } else if (cur_quick_frame_ != nullptr) {
@@ -124,13 +128,12 @@
       uint32_t method_index = inline_info.GetMethodIndexAtDepth(depth_in_stack_map);
       InvokeType invoke_type =
           static_cast<InvokeType>(inline_info.GetInvokeTypeAtDepth(depth_in_stack_map));
-      return GetResolvedMethod(GetCurrentQuickFrame()->AsMirrorPtr(), method_index, invoke_type);
+      return GetResolvedMethod(*GetCurrentQuickFrame(), method_index, invoke_type);
     } else {
-      return cur_quick_frame_->AsMirrorPtr();
+      return *cur_quick_frame_;
     }
-  } else {
-    return nullptr;
   }
+  return nullptr;
 }
 
 uint32_t StackVisitor::GetDexPc(bool abort_on_failure) const {
@@ -148,11 +151,12 @@
   }
 }
 
-extern "C" mirror::Object* artQuickGetProxyThisObject(StackReference<mirror::ArtMethod>* sp)
+extern "C" mirror::Object* artQuickGetProxyThisObject(ArtMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 mirror::Object* StackVisitor::GetThisObject() const {
-  mirror::ArtMethod* m = GetMethod();
+  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
+  ArtMethod* m = GetMethod();
   if (m->IsStatic()) {
     return nullptr;
   } else if (m->IsNative()) {
@@ -191,7 +195,7 @@
   return GetMethod()->NativeQuickPcOffset(cur_quick_frame_pc_);
 }
 
-bool StackVisitor::IsReferenceVReg(mirror::ArtMethod* m, uint16_t vreg) {
+bool StackVisitor::IsReferenceVReg(ArtMethod* m, uint16_t vreg) {
   // Process register map (which native and runtime methods don't have)
   if (m->IsNative() || m->IsRuntimeMethod() || m->IsProxyMethod()) {
     return false;
@@ -218,8 +222,7 @@
   return vreg < num_regs && TestBitmap(vreg, reg_bitmap);
 }
 
-bool StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
-                           uint32_t* val) const {
+bool StackVisitor::GetVReg(ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const {
   if (cur_quick_frame_ != nullptr) {
     DCHECK(context_ != nullptr);  // You can't reliably read registers without a context.
     DCHECK(m == GetMethod());
@@ -235,7 +238,7 @@
   }
 }
 
-bool StackVisitor::GetVRegFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
+bool StackVisitor::GetVRegFromQuickCode(ArtMethod* m, uint16_t vreg, VRegKind kind,
                                         uint32_t* val) const {
   const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
   DCHECK(code_pointer != nullptr);
@@ -258,7 +261,7 @@
   }
 }
 
-bool StackVisitor::GetVRegFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
+bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKind kind,
                                             uint32_t* val) const {
   DCHECK_EQ(m, GetMethod());
   const DexFile::CodeItem* code_item = m->GetCodeItem();
@@ -267,7 +270,7 @@
   uint16_t number_of_dex_registers = code_item->registers_size_;
   DCHECK_LT(vreg, code_item->registers_size_);
 
-  mirror::ArtMethod* outer_method = GetCurrentQuickFrame()->AsMirrorPtr();
+  ArtMethod* outer_method = *GetCurrentQuickFrame();
   const void* code_pointer = outer_method->GetQuickOatCodePointer(sizeof(void*));
   DCHECK(code_pointer != nullptr);
   CodeInfo code_info = outer_method->GetOptimizedCodeInfo();
@@ -332,7 +335,7 @@
   return true;
 }
 
-bool StackVisitor::GetVRegPair(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind_lo,
+bool StackVisitor::GetVRegPair(ArtMethod* m, uint16_t vreg, VRegKind kind_lo,
                                VRegKind kind_hi, uint64_t* val) const {
   if (kind_lo == kLongLoVReg) {
     DCHECK_EQ(kind_hi, kLongHiVReg);
@@ -357,7 +360,7 @@
   }
 }
 
-bool StackVisitor::GetVRegPairFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind_lo,
+bool StackVisitor::GetVRegPairFromQuickCode(ArtMethod* m, uint16_t vreg, VRegKind kind_lo,
                                             VRegKind kind_hi, uint64_t* val) const {
   const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
   DCHECK(code_pointer != nullptr);
@@ -384,7 +387,7 @@
   }
 }
 
-bool StackVisitor::GetVRegPairFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg,
+bool StackVisitor::GetVRegPairFromOptimizedCode(ArtMethod* m, uint16_t vreg,
                                                 VRegKind kind_lo, VRegKind kind_hi,
                                                 uint64_t* val) const {
   uint32_t low_32bits;
@@ -416,7 +419,7 @@
   return true;
 }
 
-bool StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value,
+bool StackVisitor::SetVReg(ArtMethod* m, uint16_t vreg, uint32_t new_value,
                            VRegKind kind) {
   if (cur_quick_frame_ != nullptr) {
       DCHECK(context_ != nullptr);  // You can't reliably write registers without a context.
@@ -432,7 +435,7 @@
     }
 }
 
-bool StackVisitor::SetVRegFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value,
+bool StackVisitor::SetVRegFromQuickCode(ArtMethod* m, uint16_t vreg, uint32_t new_value,
                                         VRegKind kind) {
   DCHECK(context_ != nullptr);  // You can't reliably write registers without a context.
   DCHECK(m == GetMethod());
@@ -490,7 +493,7 @@
   return true;
 }
 
-bool StackVisitor::SetVRegPair(mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value,
+bool StackVisitor::SetVRegPair(ArtMethod* m, uint16_t vreg, uint64_t new_value,
                                VRegKind kind_lo, VRegKind kind_hi) {
   if (kind_lo == kLongLoVReg) {
     DCHECK_EQ(kind_hi, kLongHiVReg);
@@ -515,7 +518,7 @@
 }
 
 bool StackVisitor::SetVRegPairFromQuickCode(
-    mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value, VRegKind kind_lo, VRegKind kind_hi) {
+    ArtMethod* m, uint16_t vreg, uint64_t new_value, VRegKind kind_lo, VRegKind kind_hi) {
   const void* code_pointer = m->GetQuickOatCodePointer(sizeof(void*));
   DCHECK(code_pointer != nullptr);
   const VmapTable vmap_table(m->GetVmapTable(code_pointer, sizeof(void*)));
@@ -631,7 +634,7 @@
   return visitor.frames;
 }
 
-bool StackVisitor::GetNextMethodAndDexPc(mirror::ArtMethod** next_method, uint32_t* next_dex_pc) {
+bool StackVisitor::GetNextMethodAndDexPc(ArtMethod** next_method, uint32_t* next_dex_pc) {
   struct HasMoreFramesVisitor : public StackVisitor {
     HasMoreFramesVisitor(Thread* thread,
                          StackWalkKind walk_kind,
@@ -647,7 +650,7 @@
 
     bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
       if (found_frame_) {
-        mirror::ArtMethod* method = GetMethod();
+        ArtMethod* method = GetMethod();
         if (method != nullptr && !method->IsRuntimeMethod()) {
           has_more_frames_ = true;
           next_method_ = method;
@@ -663,7 +666,7 @@
     size_t frame_height_;
     bool found_frame_;
     bool has_more_frames_;
-    mirror::ArtMethod* next_method_;
+    ArtMethod* next_method_;
     uint32_t next_dex_pc_;
   };
   HasMoreFramesVisitor visitor(thread_, walk_kind_, GetNumFrames(), GetFrameHeight());
@@ -689,7 +692,7 @@
 
 std::string StackVisitor::DescribeLocation() const {
   std::string result("Visiting method '");
-  mirror::ArtMethod* m = GetMethod();
+  ArtMethod* m = GetMethod();
   if (m == nullptr) {
     return "upcall";
   }
@@ -709,8 +712,34 @@
 
 void StackVisitor::SanityCheckFrame() const {
   if (kIsDebugBuild) {
-    mirror::ArtMethod* method = GetMethod();
-    CHECK_EQ(method->GetClass(), mirror::ArtMethod::GetJavaLangReflectArtMethod());
+    ArtMethod* method = GetMethod();
+    auto* declaring_class = method->GetDeclaringClass();
+    // Runtime methods have null declaring class.
+    if (!method->IsRuntimeMethod()) {
+      CHECK(declaring_class != nullptr);
+      CHECK_EQ(declaring_class->GetClass(), declaring_class->GetClass()->GetClass())
+          << declaring_class;
+    } else {
+      CHECK(declaring_class == nullptr);
+    }
+    auto* runtime = Runtime::Current();
+    auto* la = runtime->GetLinearAlloc();
+    if (!la->Contains(method)) {
+      // Check image space.
+      bool in_image = false;
+      for (auto& space : runtime->GetHeap()->GetContinuousSpaces()) {
+        if (space->IsImageSpace()) {
+          auto* image_space = space->AsImageSpace();
+          const auto& header = image_space->GetImageHeader();
+          const auto* methods = &header.GetMethodsSection();
+          if (methods->Contains(reinterpret_cast<const uint8_t*>(method) - image_space->Begin())) {
+            in_image = true;
+            break;
+          }
+        }
+      }
+      CHECK(in_image) << PrettyMethod(method) << " not in linear alloc or image";
+    }
     if (cur_quick_frame_ != nullptr) {
       method->AssertPcIsWithinQuickCode(cur_quick_frame_pc_);
       // Frame sanity.
@@ -746,7 +775,7 @@
     if (cur_quick_frame_ != nullptr) {  // Handle quick stack frames.
       // Can't be both a shadow and a quick fragment.
       DCHECK(current_fragment->GetTopShadowFrame() == nullptr);
-      mirror::ArtMethod* method = cur_quick_frame_->AsMirrorPtr();
+      ArtMethod* method = *cur_quick_frame_;
       while (method != nullptr) {
         SanityCheckFrame();
 
@@ -793,8 +822,7 @@
             if (GetMethod() == Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveAll)) {
               // Skip runtime save all callee frames which are used to deliver exceptions.
             } else if (instrumentation_frame.interpreter_entry_) {
-              mirror::ArtMethod* callee =
-                  Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
+              ArtMethod* callee = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
               CHECK_EQ(GetMethod(), callee) << "Expected: " << PrettyMethod(callee) << " Found: "
                                             << PrettyMethod(GetMethod());
             } else if (instrumentation_frame.method_ != GetMethod()) {
@@ -813,9 +841,20 @@
         }
         cur_quick_frame_pc_ = return_pc;
         uint8_t* next_frame = reinterpret_cast<uint8_t*>(cur_quick_frame_) + frame_size;
-        cur_quick_frame_ = reinterpret_cast<StackReference<mirror::ArtMethod>*>(next_frame);
+        cur_quick_frame_ = reinterpret_cast<ArtMethod**>(next_frame);
+
+        if (kDebugStackWalk) {
+          LOG(INFO) << PrettyMethod(method) << "@" << method << " size=" << frame_size
+              << " optimized=" << method->IsOptimized(sizeof(void*))
+              << " native=" << method->IsNative()
+              << " entrypoints=" << method->GetEntryPointFromQuickCompiledCode()
+              << "," << method->GetEntryPointFromJni()
+              << "," << method->GetEntryPointFromInterpreter()
+              << " next=" << *cur_quick_frame_;
+        }
+
         cur_depth_++;
-        method = cur_quick_frame_->AsMirrorPtr();
+        method = *cur_quick_frame_;
       }
     } else if (cur_shadow_frame_ != nullptr) {
       do {
@@ -848,4 +887,42 @@
       visitor->DescribeLocation() << " vreg=" << vreg_;
 }
 
+int StackVisitor::GetVRegOffsetFromQuickCode(const DexFile::CodeItem* code_item,
+                                             uint32_t core_spills, uint32_t fp_spills,
+                                             size_t frame_size, int reg, InstructionSet isa) {
+  size_t pointer_size = InstructionSetPointerSize(isa);
+  if (kIsDebugBuild) {
+    auto* runtime = Runtime::Current();
+    if (runtime != nullptr) {
+      CHECK_EQ(runtime->GetClassLinker()->GetImagePointerSize(), pointer_size);
+    }
+  }
+  DCHECK_EQ(frame_size & (kStackAlignment - 1), 0U);
+  DCHECK_NE(reg, -1);
+  int spill_size = POPCOUNT(core_spills) * GetBytesPerGprSpillLocation(isa)
+      + POPCOUNT(fp_spills) * GetBytesPerFprSpillLocation(isa)
+      + sizeof(uint32_t);  // Filler.
+  int num_regs = code_item->registers_size_ - code_item->ins_size_;
+  int temp_threshold = code_item->registers_size_;
+  const int max_num_special_temps = 1;
+  if (reg == temp_threshold) {
+    // The current method pointer corresponds to special location on stack.
+    return 0;
+  } else if (reg >= temp_threshold + max_num_special_temps) {
+    /*
+     * Special temporaries may have custom locations and the logic above deals with that.
+     * However, non-special temporaries are placed relative to the outs.
+     */
+    int temps_start = code_item->outs_size_ * sizeof(uint32_t) + pointer_size /* art method */;
+    int relative_offset = (reg - (temp_threshold + max_num_special_temps)) * sizeof(uint32_t);
+    return temps_start + relative_offset;
+  }  else if (reg < num_regs) {
+    int locals_start = frame_size - spill_size - num_regs * sizeof(uint32_t);
+    return locals_start + (reg * sizeof(uint32_t));
+  } else {
+    // Handle ins.
+    return frame_size + ((reg - num_regs) * sizeof(uint32_t)) + pointer_size /* art method */;
+  }
+}
+
 }  // namespace art
diff --git a/runtime/stack.h b/runtime/stack.h
index 0db0266..79d2f40 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -31,10 +31,10 @@
 namespace art {
 
 namespace mirror {
-  class ArtMethod;
   class Object;
 }  // namespace mirror
 
+class ArtMethod;
 class Context;
 class HandleScope;
 class InlineInfo;
@@ -76,7 +76,7 @@
 
   // Create ShadowFrame in heap for deoptimization.
   static ShadowFrame* CreateDeoptimizedFrame(uint32_t num_vregs, ShadowFrame* link,
-                                             mirror::ArtMethod* method, uint32_t dex_pc) {
+                                             ArtMethod* method, uint32_t dex_pc) {
     uint8_t* memory = new uint8_t[ComputeSize(num_vregs)];
     return Create(num_vregs, link, method, dex_pc, memory);
   }
@@ -89,7 +89,7 @@
 
   // Create ShadowFrame for interpreter using provided memory.
   static ShadowFrame* Create(uint32_t num_vregs, ShadowFrame* link,
-                             mirror::ArtMethod* method, uint32_t dex_pc, void* memory) {
+                             ArtMethod* method, uint32_t dex_pc, void* memory) {
     ShadowFrame* sf = new (memory) ShadowFrame(num_vregs, link, method, dex_pc, true);
     return sf;
   }
@@ -239,16 +239,11 @@
     }
   }
 
-  mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(method_ != nullptr);
     return method_;
   }
 
-  mirror::ArtMethod** GetMethodAddress() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(method_ != nullptr);
-    return &method_;
-  }
-
   mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -285,7 +280,7 @@
   }
 
  private:
-  ShadowFrame(uint32_t num_vregs, ShadowFrame* link, mirror::ArtMethod* method,
+  ShadowFrame(uint32_t num_vregs, ShadowFrame* link, ArtMethod* method,
               uint32_t dex_pc, bool has_reference_array)
       : number_of_vregs_(num_vregs), link_(link), method_(method), dex_pc_(dex_pc) {
     if (has_reference_array) {
@@ -309,7 +304,7 @@
   const uint32_t number_of_vregs_;
   // Link to previous shadow frame or null.
   ShadowFrame* link_;
-  mirror::ArtMethod* method_;
+  ArtMethod* method_;
   uint32_t dex_pc_;
   uint32_t vregs_[0];
 
@@ -357,11 +352,11 @@
     return link_;
   }
 
-  StackReference<mirror::ArtMethod>* GetTopQuickFrame() const {
+  ArtMethod** GetTopQuickFrame() const {
     return top_quick_frame_;
   }
 
-  void SetTopQuickFrame(StackReference<mirror::ArtMethod>* top) {
+  void SetTopQuickFrame(ArtMethod** top) {
     DCHECK(top_shadow_frame_ == nullptr);
     top_quick_frame_ = top;
   }
@@ -404,7 +399,7 @@
   bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const;
 
  private:
-  StackReference<mirror::ArtMethod>* top_quick_frame_;
+  ArtMethod** top_quick_frame_;
   ManagedStack* link_;
   ShadowFrame* top_shadow_frame_;
 };
@@ -431,7 +426,7 @@
   void WalkStack(bool include_transitions = false)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  ArtMethod* GetMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsShadowFrame() const {
     return cur_shadow_frame_ != nullptr;
@@ -477,30 +472,30 @@
   }
 
   // Get the method and dex pc immediately after the one that's currently being visited.
-  bool GetNextMethodAndDexPc(mirror::ArtMethod** next_method, uint32_t* next_dex_pc)
+  bool GetNextMethodAndDexPc(ArtMethod** next_method, uint32_t* next_dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool IsReferenceVReg(mirror::ArtMethod* m, uint16_t vreg)
+  bool IsReferenceVReg(ArtMethod* m, uint16_t vreg)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const
+  bool GetVReg(ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool GetVRegPair(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind_lo, VRegKind kind_hi,
+  bool GetVRegPair(ArtMethod* m, uint16_t vreg, VRegKind kind_lo, VRegKind kind_hi,
                    uint64_t* val) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind)
+  bool SetVReg(ArtMethod* m, uint16_t vreg, uint32_t new_value, VRegKind kind)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool SetVRegPair(mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value,
+  bool SetVRegPair(ArtMethod* m, uint16_t vreg, uint64_t new_value,
                    VRegKind kind_lo, VRegKind kind_hi)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   uintptr_t* GetGPRAddress(uint32_t reg) const;
 
   // This is a fast-path for getting/setting values in a quick frame.
-  uint32_t* GetVRegAddrFromQuickCode(StackReference<mirror::ArtMethod>* cur_quick_frame,
+  uint32_t* GetVRegAddrFromQuickCode(ArtMethod** cur_quick_frame,
                                      const DexFile::CodeItem* code_item,
                                      uint32_t core_spills, uint32_t fp_spills, size_t frame_size,
                                      uint16_t vreg) const {
@@ -534,7 +529,7 @@
    *     | IN[ins-1]                     |  {Note: resides in caller's frame}
    *     |       .                       |
    *     | IN[0]                         |
-   *     | caller's ArtMethod            |  ... StackReference<ArtMethod>
+   *     | caller's ArtMethod            |  ... ArtMethod*
    *     +===============================+  {Note: start of callee's frame}
    *     | core callee-save spill        |  {variable sized}
    *     +-------------------------------+
@@ -561,46 +556,16 @@
    *     | OUT[outs-2]                   |
    *     |       .                       |
    *     | OUT[0]                        |
-   *     | StackReference<ArtMethod>     |  ... (reg == num_total_code_regs == special_temp_value) <<== sp, 16-byte aligned
+   *     | ArtMethod*                    |  ... (reg == num_total_code_regs == special_temp_value) <<== sp, 16-byte aligned
    *     +===============================+
    */
   static int GetVRegOffsetFromQuickCode(const DexFile::CodeItem* code_item,
                                         uint32_t core_spills, uint32_t fp_spills,
-                                        size_t frame_size, int reg, InstructionSet isa) {
-    DCHECK_EQ(frame_size & (kStackAlignment - 1), 0U);
-    DCHECK_NE(reg, -1);
-    int spill_size = POPCOUNT(core_spills) * GetBytesPerGprSpillLocation(isa)
-        + POPCOUNT(fp_spills) * GetBytesPerFprSpillLocation(isa)
-        + sizeof(uint32_t);  // Filler.
-    int num_regs = code_item->registers_size_ - code_item->ins_size_;
-    int temp_threshold = code_item->registers_size_;
-    const int max_num_special_temps = 1;
-    if (reg == temp_threshold) {
-      // The current method pointer corresponds to special location on stack.
-      return 0;
-    } else if (reg >= temp_threshold + max_num_special_temps) {
-      /*
-       * Special temporaries may have custom locations and the logic above deals with that.
-       * However, non-special temporaries are placed relative to the outs.
-       */
-      int temps_start = sizeof(StackReference<mirror::ArtMethod>) +
-          code_item->outs_size_ * sizeof(uint32_t);
-      int relative_offset = (reg - (temp_threshold + max_num_special_temps)) * sizeof(uint32_t);
-      return temps_start + relative_offset;
-    }  else if (reg < num_regs) {
-      int locals_start = frame_size - spill_size - num_regs * sizeof(uint32_t);
-      return locals_start + (reg * sizeof(uint32_t));
-    } else {
-      // Handle ins.
-      return frame_size + ((reg - num_regs) * sizeof(uint32_t)) +
-          sizeof(StackReference<mirror::ArtMethod>);
-    }
-  }
+                                        size_t frame_size, int reg, InstructionSet isa);
 
   static int GetOutVROffset(uint16_t out_num, InstructionSet isa) {
-    UNUSED(isa);
     // According to stack model, the first out is above the Method referernce.
-    return sizeof(StackReference<mirror::ArtMethod>) + (out_num * sizeof(uint32_t));
+    return InstructionSetPointerSize(isa) + out_num * sizeof(uint32_t);
   }
 
   bool IsInInlinedFrame() const {
@@ -611,7 +576,7 @@
     return cur_quick_frame_pc_;
   }
 
-  StackReference<mirror::ArtMethod>* GetCurrentQuickFrame() const {
+  ArtMethod** GetCurrentQuickFrame() const {
     return cur_quick_frame_;
   }
 
@@ -619,10 +584,10 @@
     return cur_shadow_frame_;
   }
 
-  HandleScope* GetCurrentHandleScope() const {
-    StackReference<mirror::ArtMethod>* sp = GetCurrentQuickFrame();
-    ++sp;  // Skip Method*; handle scope comes next;
-    return reinterpret_cast<HandleScope*>(sp);
+  HandleScope* GetCurrentHandleScope(size_t pointer_size) const {
+    ArtMethod** sp = GetCurrentQuickFrame();
+    // Skip ArtMethod*; handle scope comes next;
+    return reinterpret_cast<HandleScope*>(reinterpret_cast<uintptr_t>(sp) + pointer_size);
   }
 
   std::string DescribeLocation() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -661,19 +626,19 @@
   uintptr_t GetFPR(uint32_t reg) const;
   void SetFPR(uint32_t reg, uintptr_t value);
 
-  bool GetVRegFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
+  bool GetVRegFromQuickCode(ArtMethod* m, uint16_t vreg, VRegKind kind,
                             uint32_t* val) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool GetVRegFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind,
+  bool GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKind kind,
                                 uint32_t* val) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool GetRegisterIfAccessible(uint32_t reg, VRegKind kind, uint32_t* val) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool GetVRegPairFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind_lo,
+  bool GetVRegPairFromQuickCode(ArtMethod* m, uint16_t vreg, VRegKind kind_lo,
                                 VRegKind kind_hi, uint64_t* val) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  bool GetVRegPairFromOptimizedCode(mirror::ArtMethod* m, uint16_t vreg,
+  bool GetVRegPairFromOptimizedCode(ArtMethod* m, uint16_t vreg,
                                     VRegKind kind_lo, VRegKind kind_hi,
                                     uint64_t* val) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -681,13 +646,13 @@
                                    uint64_t* val) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool SetVRegFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_value,
+  bool SetVRegFromQuickCode(ArtMethod* m, uint16_t vreg, uint32_t new_value,
                             VRegKind kind)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool SetRegisterIfAccessible(uint32_t reg, uint32_t new_value, VRegKind kind)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  bool SetVRegPairFromQuickCode(mirror::ArtMethod* m, uint16_t vreg, uint64_t new_value,
+  bool SetVRegPairFromQuickCode(ArtMethod* m, uint16_t vreg, uint64_t new_value,
                                 VRegKind kind_lo, VRegKind kind_hi)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool SetRegisterPairIfAccessible(uint32_t reg_lo, uint32_t reg_hi, uint64_t new_value,
@@ -701,7 +666,7 @@
   Thread* const thread_;
   const StackWalkKind walk_kind_;
   ShadowFrame* cur_shadow_frame_;
-  StackReference<mirror::ArtMethod>* cur_quick_frame_;
+  ArtMethod** cur_quick_frame_;
   uintptr_t cur_quick_frame_pc_;
   // Lazily computed, number of frames in the stack.
   size_t num_frames_;
diff --git a/runtime/stride_iterator.h b/runtime/stride_iterator.h
new file mode 100644
index 0000000..5971524
--- /dev/null
+++ b/runtime/stride_iterator.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_STRIDE_ITERATOR_H_
+#define ART_RUNTIME_STRIDE_ITERATOR_H_
+
+#include <iterator>
+
+namespace art {
+
+template<typename T>
+class StrideIterator : public std::iterator<std::random_access_iterator_tag, T> {
+ public:
+  StrideIterator(const StrideIterator&) = default;
+  StrideIterator(StrideIterator&&) = default;
+  StrideIterator& operator=(const StrideIterator&) = default;
+  StrideIterator& operator=(StrideIterator&&) = default;
+
+  StrideIterator(uintptr_t ptr, size_t stride)
+      : ptr_(ptr), stride_(stride) {
+  }
+
+  bool operator==(const StrideIterator& other) const {
+    return ptr_ == other.ptr_;
+  }
+
+  bool operator!=(const StrideIterator& other) const {
+    return !(*this == other);
+  }
+
+  StrideIterator operator++() {  // Value after modification.
+    ptr_ += stride_;
+    return *this;
+  }
+
+  StrideIterator operator++(int) {
+    auto temp = *this;
+    ptr_ += stride_;
+    return temp;
+  }
+
+  T& operator*() const {
+    return *reinterpret_cast<T*>(ptr_);
+  }
+
+  T* operator->() const {
+    return &**this;
+  }
+
+ private:
+  uintptr_t ptr_;
+  const size_t stride_;
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_STRIDE_ITERATOR_H_
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 6f734dd..89e3467 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -33,6 +33,7 @@
 
 #include "arch/context.h"
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/bit_utils.h"
 #include "base/mutex.h"
 #include "base/timing_logger.h"
@@ -50,7 +51,6 @@
 #include "handle_scope-inl.h"
 #include "indirect_reference_table-inl.h"
 #include "jni_internal.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/class-inl.h"
 #include "mirror/object_array-inl.h"
@@ -756,7 +756,7 @@
   union StateAndFlags new_state_and_flags;
   new_state_and_flags.as_int = old_state_and_flags.as_int;
   new_state_and_flags.as_struct.flags |= kCheckpointRequest;
-  bool success =tls32_.state_and_flags.as_atomic_int.CompareExchangeStrongSequentiallyConsistent(
+  bool success = tls32_.state_and_flags.as_atomic_int.CompareExchangeStrongSequentiallyConsistent(
       old_state_and_flags.as_int, new_state_and_flags.as_int);
   if (UNLIKELY(!success)) {
     // The thread changed state before the checkpoint was installed.
@@ -958,7 +958,7 @@
   }
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     if (m->IsRuntimeMethod()) {
       return true;
     }
@@ -1029,7 +1029,7 @@
   std::ostream& os;
   const Thread* thread;
   const bool can_allocate;
-  mirror::ArtMethod* last_method;
+  ArtMethod* last_method;
   int last_line_number;
   int repetition_count;
   int frame_count;
@@ -1060,7 +1060,7 @@
   // We don't just check kNative because native methods will be in state kSuspended if they're
   // calling back into the VM, or kBlocked if they're blocked on a monitor, or one of the
   // thread-startup states if it's early enough in their life cycle (http://b/7432159).
-  mirror::ArtMethod* current_method = thread->GetCurrentMethod(nullptr);
+  ArtMethod* current_method = thread->GetCurrentMethod(nullptr);
   return current_method != nullptr && current_method->IsNative();
 }
 
@@ -1541,7 +1541,7 @@
     // We want to skip frames up to and including the exception's constructor.
     // Note we also skip the frame if it doesn't have a method (namely the callee
     // save frame)
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     if (skipping_ && !m->IsRuntimeMethod() &&
         !mirror::Throwable::GetJavaLangThrowable()->IsAssignableFrom(m->GetDeclaringClass())) {
       skipping_ = false;
@@ -1578,63 +1578,54 @@
         self_(self),
         skip_depth_(skip_depth),
         count_(0),
-        dex_pc_trace_(nullptr),
-        method_trace_(nullptr) {}
+        trace_(nullptr),
+        pointer_size_(Runtime::Current()->GetClassLinker()->GetImagePointerSize()) {}
 
   bool Init(int depth)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // Allocate method trace with an extra slot that will hold the PC trace
-    StackHandleScope<1> hs(self_);
-    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    Handle<mirror::ObjectArray<mirror::Object>> method_trace(
-        hs.NewHandle(class_linker->AllocObjectArray<mirror::Object>(self_, depth + 1)));
-    if (method_trace.Get() == nullptr) {
+    auto* cl = Runtime::Current()->GetClassLinker();
+    trace_ = cl->AllocPointerArray(self_, depth * 2);
+    if (trace_ == nullptr) {
+      self_->AssertPendingOOMException();
       return false;
     }
-    mirror::IntArray* dex_pc_trace = mirror::IntArray::Alloc(self_, depth);
-    if (dex_pc_trace == nullptr) {
-      return false;
-    }
-    // Save PC trace in last element of method trace, also places it into the
-    // object graph.
-    // We are called from native: use non-transactional mode.
-    method_trace->Set<kTransactionActive>(depth, dex_pc_trace);
-    // Set the Object*s and assert that no thread suspension is now possible.
+    // If We are called from native, use non-transactional mode.
     const char* last_no_suspend_cause =
         self_->StartAssertNoThreadSuspension("Building internal stack trace");
     CHECK(last_no_suspend_cause == nullptr) << last_no_suspend_cause;
-    method_trace_ = method_trace.Get();
-    dex_pc_trace_ = dex_pc_trace;
     return true;
   }
 
   virtual ~BuildInternalStackTraceVisitor() {
-    if (method_trace_ != nullptr) {
+    if (trace_ != nullptr) {
       self_->EndAssertNoThreadSuspension(nullptr);
     }
   }
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    if (method_trace_ == nullptr || dex_pc_trace_ == nullptr) {
+    if (trace_ == nullptr) {
       return true;  // We're probably trying to fillInStackTrace for an OutOfMemoryError.
     }
     if (skip_depth_ > 0) {
       skip_depth_--;
       return true;
     }
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     if (m->IsRuntimeMethod()) {
       return true;  // Ignore runtime frames (in particular callee save).
     }
-    method_trace_->Set<kTransactionActive>(count_, m);
-    dex_pc_trace_->Set<kTransactionActive>(count_,
-        m->IsProxyMethod() ? DexFile::kDexNoIndex : GetDexPc());
+    trace_->SetElementPtrSize<kTransactionActive>(
+        count_, m, pointer_size_);
+    trace_->SetElementPtrSize<kTransactionActive>(
+        trace_->GetLength() / 2 + count_, m->IsProxyMethod() ? DexFile::kDexNoIndex : GetDexPc(),
+            pointer_size_);
     ++count_;
     return true;
   }
 
-  mirror::ObjectArray<mirror::Object>* GetInternalStackTrace() const {
-    return method_trace_;
+  mirror::PointerArray* GetInternalStackTrace() const {
+    return trace_;
   }
 
  private:
@@ -1643,10 +1634,10 @@
   int32_t skip_depth_;
   // Current position down stack trace.
   uint32_t count_;
-  // Array of dex PC values.
-  mirror::IntArray* dex_pc_trace_;
-  // An array of the methods on the stack, the last entry is a reference to the PC trace.
-  mirror::ObjectArray<mirror::Object>* method_trace_;
+  // An array of the methods on the stack, the last entries are the dex PCs.
+  mirror::PointerArray* trace_;
+  // For cross compilation.
+  size_t pointer_size_;
 };
 
 template<bool kTransactionActive>
@@ -1665,13 +1656,16 @@
     return nullptr;  // Allocation failed.
   }
   build_trace_visitor.WalkStack();
-  mirror::ObjectArray<mirror::Object>* trace = build_trace_visitor.GetInternalStackTrace();
+  mirror::PointerArray* trace = build_trace_visitor.GetInternalStackTrace();
   if (kIsDebugBuild) {
-    for (int32_t i = 0; i < trace->GetLength(); ++i) {
-      CHECK(trace->Get(i) != nullptr);
+    // Second half is dex PCs.
+    for (uint32_t i = 0; i < static_cast<uint32_t>(trace->GetLength() / 2); ++i) {
+      auto* method = trace->GetElementPtrSize<ArtMethod*>(
+          i, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
+      CHECK(method != nullptr);
     }
   }
-  return soa.AddLocalReference<jobjectArray>(trace);
+  return soa.AddLocalReference<jobject>(trace);
 }
 template jobject Thread::CreateInternalStackTrace<false>(
     const ScopedObjectAccessAlreadyRunnable& soa) const;
@@ -1688,9 +1682,9 @@
     const ScopedObjectAccessAlreadyRunnable& soa, jobject internal, jobjectArray output_array,
     int* stack_depth) {
   // Decode the internal stack trace into the depth, method trace and PC trace
-  int32_t depth = soa.Decode<mirror::ObjectArray<mirror::Object>*>(internal)->GetLength() - 1;
+  int32_t depth = soa.Decode<mirror::PointerArray*>(internal)->GetLength() / 2;
 
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  auto* cl = Runtime::Current()->GetClassLinker();
 
   jobjectArray result;
 
@@ -1704,7 +1698,7 @@
   } else {
     // Create java_trace array and place in local reference table
     mirror::ObjectArray<mirror::StackTraceElement>* java_traces =
-        class_linker->AllocStackTraceElementArray(soa.Self(), depth);
+        cl->AllocStackTraceElementArray(soa.Self(), depth);
     if (java_traces == nullptr) {
       return nullptr;
     }
@@ -1716,10 +1710,11 @@
   }
 
   for (int32_t i = 0; i < depth; ++i) {
-    mirror::ObjectArray<mirror::Object>* method_trace =
-          soa.Decode<mirror::ObjectArray<mirror::Object>*>(internal);
+    auto* method_trace = soa.Decode<mirror::PointerArray*>(internal);
     // Prepare parameters for StackTraceElement(String cls, String method, String file, int line)
-    mirror::ArtMethod* method = down_cast<mirror::ArtMethod*>(method_trace->Get(i));
+    ArtMethod* method = method_trace->GetElementPtrSize<ArtMethod*>(i, sizeof(void*));
+    uint32_t dex_pc = method_trace->GetElementPtrSize<uint32_t>(
+        i + method_trace->GetLength() / 2, sizeof(void*));
     int32_t line_number;
     StackHandleScope<3> hs(soa.Self());
     auto class_name_object(hs.NewHandle<mirror::String>(nullptr));
@@ -1729,27 +1724,28 @@
       class_name_object.Assign(method->GetDeclaringClass()->GetName());
       // source_name_object intentionally left null for proxy methods
     } else {
-      mirror::IntArray* pc_trace = down_cast<mirror::IntArray*>(method_trace->Get(depth));
-      uint32_t dex_pc = pc_trace->Get(i);
       line_number = method->GetLineNumFromDexPC(dex_pc);
       // Allocate element, potentially triggering GC
       // TODO: reuse class_name_object via Class::name_?
       const char* descriptor = method->GetDeclaringClassDescriptor();
       CHECK(descriptor != nullptr);
       std::string class_name(PrettyDescriptor(descriptor));
-      class_name_object.Assign(mirror::String::AllocFromModifiedUtf8(soa.Self(), class_name.c_str()));
+      class_name_object.Assign(
+          mirror::String::AllocFromModifiedUtf8(soa.Self(), class_name.c_str()));
       if (class_name_object.Get() == nullptr) {
+        soa.Self()->AssertPendingOOMException();
         return nullptr;
       }
       const char* source_file = method->GetDeclaringClassSourceFile();
       if (source_file != nullptr) {
         source_name_object.Assign(mirror::String::AllocFromModifiedUtf8(soa.Self(), source_file));
         if (source_name_object.Get() == nullptr) {
+          soa.Self()->AssertPendingOOMException();
           return nullptr;
         }
       }
     }
-    const char* method_name = method->GetName();
+    const char* method_name = method->GetInterfaceMethodIfProxy(sizeof(void*))->GetName();
     CHECK(method_name != nullptr);
     Handle<mirror::String> method_name_object(
         hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), method_name)));
@@ -1790,7 +1786,7 @@
 
 static mirror::ClassLoader* GetCurrentClassLoader(Thread* self)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  mirror::ArtMethod* method = self->GetCurrentMethod(nullptr);
+  ArtMethod* method = self->GetCurrentMethod(nullptr);
   return method != nullptr
       ? method->GetDeclaringClass()->GetClassLoader()
       : nullptr;
@@ -1805,9 +1801,9 @@
   ScopedLocalRef<jobject> cause(GetJniEnv(), soa.AddLocalReference<jobject>(GetException()));
   ClearException();
   Runtime* runtime = Runtime::Current();
+  auto* cl = runtime->GetClassLinker();
   Handle<mirror::Class> exception_class(
-      hs.NewHandle(runtime->GetClassLinker()->FindClass(this, exception_class_descriptor,
-                                                        class_loader)));
+      hs.NewHandle(cl->FindClass(this, exception_class_descriptor, class_loader)));
   if (UNLIKELY(exception_class.Get() == nullptr)) {
     CHECK(IsExceptionPending());
     LOG(ERROR) << "No exception class " << PrettyDescriptor(exception_class_descriptor);
@@ -1852,8 +1848,8 @@
       signature = "(Ljava/lang/Throwable;)V";
     }
   }
-  mirror::ArtMethod* exception_init_method =
-      exception_class->FindDeclaredDirectMethod("<init>", signature);
+  ArtMethod* exception_init_method =
+      exception_class->FindDeclaredDirectMethod("<init>", signature, cl->GetImagePointerSize());
 
   CHECK(exception_init_method != nullptr) << "No <init>" << signature << " in "
       << PrettyDescriptor(exception_class_descriptor);
@@ -2129,7 +2125,7 @@
         dex_pc_(0),
         abort_on_error_(abort_on_error) {}
   bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     if (m->IsRuntimeMethod()) {
       // Continue if this is a runtime method.
       return true;
@@ -2142,12 +2138,12 @@
     return false;
   }
   mirror::Object* this_object_;
-  mirror::ArtMethod* method_;
+  ArtMethod* method_;
   uint32_t dex_pc_;
   const bool abort_on_error_;
 };
 
-mirror::ArtMethod* Thread::GetCurrentMethod(uint32_t* dex_pc, bool abort_on_error) const {
+ArtMethod* Thread::GetCurrentMethod(uint32_t* dex_pc, bool abort_on_error) const {
   CurrentMethodVisitor visitor(const_cast<Thread*>(this), nullptr, abort_on_error);
   visitor.WalkStack(false);
   if (dex_pc != nullptr) {
@@ -2189,9 +2185,7 @@
   }
 
   void VisitShadowFrame(ShadowFrame* shadow_frame) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod** method_addr = shadow_frame->GetMethodAddress();
-    visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this);
-    mirror::ArtMethod* m = *method_addr;
+    ArtMethod* m = shadow_frame->GetMethod();
     DCHECK(m != nullptr);
     size_t num_regs = shadow_frame->NumberOfVRegs();
     if (m->IsNative() || shadow_frame->HasReferenceArray()) {
@@ -2233,17 +2227,15 @@
 
  private:
   void VisitQuickFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    StackReference<mirror::ArtMethod>* cur_quick_frame = GetCurrentQuickFrame();
-    mirror::ArtMethod* m = cur_quick_frame->AsMirrorPtr();
-    mirror::ArtMethod* old_method = m;
-    visitor_(reinterpret_cast<mirror::Object**>(&m), 0 /*ignored*/, this);
-    if (m != old_method) {
-      cur_quick_frame->Assign(m);
-    }
+    auto* cur_quick_frame = GetCurrentQuickFrame();
+    DCHECK(cur_quick_frame != nullptr);
+    auto* m = *cur_quick_frame;
 
     // Process register map (which native and runtime methods don't have)
     if (!m->IsNative() && !m->IsRuntimeMethod() && !m->IsProxyMethod()) {
       if (m->IsOptimized(sizeof(void*))) {
+        auto* vreg_base = reinterpret_cast<StackReference<mirror::Object>*>(
+            reinterpret_cast<uintptr_t>(cur_quick_frame));
         Runtime* runtime = Runtime::Current();
         const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(m, sizeof(void*));
         uintptr_t native_pc_offset = m->NativeQuickPcOffset(GetCurrentQuickFramePc(), entry_point);
@@ -2254,8 +2246,7 @@
         // Visit stack entries that hold pointers.
         for (size_t i = 0; i < mask.size_in_bits(); ++i) {
           if (mask.LoadBit(i)) {
-            StackReference<mirror::Object>* ref_addr =
-                  reinterpret_cast<StackReference<mirror::Object>*>(cur_quick_frame) + i;
+            auto* ref_addr = vreg_base + i;
             mirror::Object* ref = ref_addr->AsMirrorPtr();
             if (ref != nullptr) {
               mirror::Object* new_ref = ref;
@@ -2291,7 +2282,7 @@
           uintptr_t native_pc_offset = m->NativeQuickPcOffset(GetCurrentQuickFramePc(), entry_point);
           const uint8_t* reg_bitmap = map.FindBitMap(native_pc_offset);
           DCHECK(reg_bitmap != nullptr);
-          const void* code_pointer = mirror::ArtMethod::EntryPointToCodePointer(entry_point);
+          const void* code_pointer = ArtMethod::EntryPointToCodePointer(entry_point);
           const VmapTable vmap_table(m->GetVmapTable(code_pointer, sizeof(void*)));
           QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo(code_pointer);
           // For all dex registers in the bitmap
@@ -2362,9 +2353,6 @@
   if (tlsPtr_.debug_invoke_req != nullptr) {
     tlsPtr_.debug_invoke_req->VisitRoots(visitor, RootInfo(kRootDebugger, thread_id));
   }
-  if (tlsPtr_.single_step_control != nullptr) {
-    tlsPtr_.single_step_control->VisitRoots(visitor, RootInfo(kRootDebugger, thread_id));
-  }
   if (tlsPtr_.deoptimization_shadow_frame != nullptr) {
     RootCallbackVisitor visitor_to_callback(visitor, thread_id);
     ReferenceMapVisitor<RootCallbackVisitor> mapper(this, nullptr, visitor_to_callback);
@@ -2393,9 +2381,6 @@
   ReleaseLongJumpContext(context);
   for (instrumentation::InstrumentationStackFrame& frame : *GetInstrumentationStack()) {
     visitor->VisitRootIfNonNull(&frame.this_object_, RootInfo(kRootVMInternal, thread_id));
-    DCHECK(frame.method_ != nullptr);
-    visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&frame.method_),
-                       RootInfo(kRootVMInternal, thread_id));
   }
 }
 
diff --git a/runtime/thread.h b/runtime/thread.h
index 96e0916..8c2e215 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -52,7 +52,6 @@
 }  // namespace gc
 
 namespace mirror {
-  class ArtMethod;
   class Array;
   class Class;
   class ClassLoader;
@@ -69,6 +68,7 @@
 class MethodVerifier;
 }  // namespace verifier
 
+class ArtMethod;
 class BaseMutex;
 class ClassLinker;
 class Closure;
@@ -374,7 +374,7 @@
 
   // Get the current method and dex pc. If there are errors in retrieving the dex pc, this will
   // abort the runtime iff abort_on_error is true.
-  mirror::ArtMethod* GetCurrentMethod(uint32_t* dex_pc, bool abort_on_error = true) const
+  ArtMethod* GetCurrentMethod(uint32_t* dex_pc, bool abort_on_error = true) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns whether the given exception was thrown by the current Java method being executed
@@ -382,7 +382,7 @@
   bool IsExceptionThrownByCurrentMethod(mirror::Throwable* exception) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void SetTopOfStack(StackReference<mirror::ArtMethod>* top_method) {
+  void SetTopOfStack(ArtMethod** top_method) {
     tlsPtr_.managed_stack.SetTopQuickFrame(top_method);
   }
 
@@ -810,11 +810,11 @@
     return tlsPtr_.instrumentation_stack;
   }
 
-  std::vector<mirror::ArtMethod*>* GetStackTraceSample() const {
+  std::vector<ArtMethod*>* GetStackTraceSample() const {
     return tlsPtr_.stack_trace_sample;
   }
 
-  void SetStackTraceSample(std::vector<mirror::ArtMethod*>* sample) {
+  void SetStackTraceSample(std::vector<ArtMethod*>* sample) {
     tlsPtr_.stack_trace_sample = sample;
   }
 
@@ -1161,7 +1161,7 @@
     size_t stack_size;
 
     // Pointer to previous stack trace captured by sampling profiler.
-    std::vector<mirror::ArtMethod*>* stack_trace_sample;
+    std::vector<ArtMethod*>* stack_trace_sample;
 
     // The next thread in the wait set this thread is part of or null if not waiting.
     Thread* wait_next;
diff --git a/runtime/trace.cc b/runtime/trace.cc
index f874716..13efb53 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -22,6 +22,7 @@
 #define ATRACE_TAG ATRACE_TAG_DALVIK
 #include "cutils/trace.h"
 
+#include "art_method-inl.h"
 #include "base/casts.h"
 #include "base/stl_util.h"
 #include "base/time_utils.h"
@@ -31,7 +32,6 @@
 #include "debugger.h"
 #include "dex_file-inl.h"
 #include "instrumentation.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/object_array-inl.h"
@@ -98,7 +98,7 @@
         method_trace_(Trace::AllocStackTrace()) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     // Ignore runtime frames (in particular callee save).
     if (!m->IsRuntimeMethod()) {
       method_trace_->push_back(m);
@@ -107,12 +107,12 @@
   }
 
   // Returns a stack trace where the topmost frame corresponds with the first element of the vector.
-  std::vector<mirror::ArtMethod*>* GetStackTrace() const {
+  std::vector<ArtMethod*>* GetStackTrace() const {
     return method_trace_;
   }
 
  private:
-  std::vector<mirror::ArtMethod*>* const method_trace_;
+  std::vector<ArtMethod*>* const method_trace_;
 };
 
 static const char     kTraceTokenChar             = '*';
@@ -120,42 +120,41 @@
 static const uint32_t kTraceMagicValue            = 0x574f4c53;
 static const uint16_t kTraceVersionSingleClock    = 2;
 static const uint16_t kTraceVersionDualClock      = 3;
-static const uint16_t kTraceRecordSizeSingleClock = 10;  // using v2
-static const uint16_t kTraceRecordSizeDualClock   = 14;  // using v3 with two timestamps
+static const uint16_t kTraceRecordSizeSingleClock = 14;  // using v2
+static const uint16_t kTraceRecordSizeDualClock   = 18;  // using v3 with two timestamps
 
 TraceClockSource Trace::default_clock_source_ = kDefaultTraceClockSource;
 
 Trace* volatile Trace::the_trace_ = nullptr;
 pthread_t Trace::sampling_pthread_ = 0U;
-std::unique_ptr<std::vector<mirror::ArtMethod*>> Trace::temp_stack_trace_;
+std::unique_ptr<std::vector<ArtMethod*>> Trace::temp_stack_trace_;
 
 // The key identifying the tracer to update instrumentation.
 static constexpr const char* kTracerInstrumentationKey = "Tracer";
 
-static mirror::ArtMethod* DecodeTraceMethodId(uint32_t tmid) {
-  return reinterpret_cast<mirror::ArtMethod*>(tmid & ~kTraceMethodActionMask);
+static ArtMethod* DecodeTraceMethodId(uint64_t tmid) {
+  return reinterpret_cast<ArtMethod*>(tmid & ~kTraceMethodActionMask);
 }
 
 static TraceAction DecodeTraceAction(uint32_t tmid) {
   return static_cast<TraceAction>(tmid & kTraceMethodActionMask);
 }
 
-static uint32_t EncodeTraceMethodAndAction(mirror::ArtMethod* method,
-                                           TraceAction action) {
-  uint32_t tmid = PointerToLowMemUInt32(method) | action;
+static uint64_t EncodeTraceMethodAndAction(ArtMethod* method, TraceAction action) {
+  auto tmid = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(method)) | action;
   DCHECK_EQ(method, DecodeTraceMethodId(tmid));
   return tmid;
 }
 
-std::vector<mirror::ArtMethod*>* Trace::AllocStackTrace() {
+std::vector<ArtMethod*>* Trace::AllocStackTrace() {
   if (temp_stack_trace_.get() != nullptr) {
     return temp_stack_trace_.release();
   } else {
-    return new std::vector<mirror::ArtMethod*>();
+    return new std::vector<ArtMethod*>();
   }
 }
 
-void Trace::FreeStackTrace(std::vector<mirror::ArtMethod*>* stack_trace) {
+void Trace::FreeStackTrace(std::vector<ArtMethod*>* stack_trace) {
   stack_trace->clear();
   temp_stack_trace_.reset(stack_trace);
 }
@@ -248,22 +247,22 @@
 static void GetSample(Thread* thread, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   BuildStackTraceVisitor build_trace_visitor(thread);
   build_trace_visitor.WalkStack();
-  std::vector<mirror::ArtMethod*>* stack_trace = build_trace_visitor.GetStackTrace();
+  std::vector<ArtMethod*>* stack_trace = build_trace_visitor.GetStackTrace();
   Trace* the_trace = reinterpret_cast<Trace*>(arg);
   the_trace->CompareAndUpdateStackTrace(thread, stack_trace);
 }
 
 static void ClearThreadStackTraceAndClockBase(Thread* thread, void* arg ATTRIBUTE_UNUSED) {
   thread->SetTraceClockBase(0);
-  std::vector<mirror::ArtMethod*>* stack_trace = thread->GetStackTraceSample();
+  std::vector<ArtMethod*>* stack_trace = thread->GetStackTraceSample();
   thread->SetStackTraceSample(nullptr);
   delete stack_trace;
 }
 
 void Trace::CompareAndUpdateStackTrace(Thread* thread,
-                                       std::vector<mirror::ArtMethod*>* stack_trace) {
+                                       std::vector<ArtMethod*>* stack_trace) {
   CHECK_EQ(pthread_self(), sampling_pthread_);
-  std::vector<mirror::ArtMethod*>* old_stack_trace = thread->GetStackTraceSample();
+  std::vector<ArtMethod*>* old_stack_trace = thread->GetStackTraceSample();
   // Update the thread's stack trace sample.
   thread->SetStackTraceSample(stack_trace);
   // Read timer clocks to use for all events in this trace.
@@ -273,7 +272,7 @@
   if (old_stack_trace == nullptr) {
     // If there's no previous stack trace sample for this thread, log an entry event for all
     // methods in the trace.
-    for (std::vector<mirror::ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
+    for (std::vector<ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
          rit != stack_trace->rend(); ++rit) {
       LogMethodTraceEvent(thread, *rit, instrumentation::Instrumentation::kMethodEntered,
                           thread_clock_diff, wall_clock_diff);
@@ -281,15 +280,15 @@
   } else {
     // If there's a previous stack trace for this thread, diff the traces and emit entry and exit
     // events accordingly.
-    std::vector<mirror::ArtMethod*>::reverse_iterator old_rit = old_stack_trace->rbegin();
-    std::vector<mirror::ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
+    std::vector<ArtMethod*>::reverse_iterator old_rit = old_stack_trace->rbegin();
+    std::vector<ArtMethod*>::reverse_iterator rit = stack_trace->rbegin();
     // Iterate bottom-up over both traces until there's a difference between them.
     while (old_rit != old_stack_trace->rend() && rit != stack_trace->rend() && *old_rit == *rit) {
       old_rit++;
       rit++;
     }
     // Iterate top-down over the old trace until the point where they differ, emitting exit events.
-    for (std::vector<mirror::ArtMethod*>::iterator old_it = old_stack_trace->begin();
+    for (std::vector<ArtMethod*>::iterator old_it = old_stack_trace->begin();
          old_it != old_rit.base(); ++old_it) {
       LogMethodTraceEvent(thread, *old_it, instrumentation::Instrumentation::kMethodExited,
                           thread_clock_diff, wall_clock_diff);
@@ -640,14 +639,22 @@
   delete streaming_lock_;
 }
 
+static uint64_t ReadBytes(uint8_t* buf, size_t bytes) {
+  uint64_t ret = 0;
+  for (size_t i = 0; i < bytes; ++i) {
+    ret |= static_cast<uint64_t>(buf[i]) << (i * 8);
+  }
+  return ret;
+}
+
 static void DumpBuf(uint8_t* buf, size_t buf_size, TraceClockSource clock_source)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   uint8_t* ptr = buf + kTraceHeaderLength;
   uint8_t* end = buf + buf_size;
 
   while (ptr < end) {
-    uint32_t tmid = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24);
-    mirror::ArtMethod* method = DecodeTraceMethodId(tmid);
+    uint64_t tmid = ReadBytes(ptr + 2, sizeof(tmid));
+    ArtMethod* method = DecodeTraceMethodId(tmid);
     TraceAction action = DecodeTraceAction(tmid);
     LOG(INFO) << PrettyMethod(method) << " " << static_cast<int>(action);
     ptr += GetRecordSize(clock_source);
@@ -656,12 +663,12 @@
 
 static void GetVisitedMethodsFromBitSets(
     const std::map<mirror::DexCache*, DexIndexBitSet*>& seen_methods,
-    std::set<mirror::ArtMethod*>* visited_methods) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    std::set<ArtMethod*>* visited_methods) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   for (auto& e : seen_methods) {
     DexIndexBitSet* bit_set = e.second;
     for (uint32_t i = 0; i < bit_set->size(); ++i) {
       if ((*bit_set)[i]) {
-        visited_methods->insert(e.first->GetResolvedMethod(i));
+        visited_methods->insert(e.first->GetResolvedMethod(i, sizeof(void*)));
       }
     }
   }
@@ -670,7 +677,7 @@
 void Trace::FinishTracing() {
   size_t final_offset = 0;
 
-  std::set<mirror::ArtMethod*> visited_methods;
+  std::set<ArtMethod*> visited_methods;
   if (trace_output_mode_ == TraceOutputMode::kStreaming) {
     // Write the secondary file with all the method names.
     GetVisitedMethodsFromBitSets(seen_methods_, &visited_methods);
@@ -761,14 +768,14 @@
 }
 
 void Trace::DexPcMoved(Thread* thread, mirror::Object* this_object,
-                       mirror::ArtMethod* method, uint32_t new_dex_pc) {
+                       ArtMethod* method, uint32_t new_dex_pc) {
   UNUSED(thread, this_object, method, new_dex_pc);
   // We're not recorded to listen to this kind of event, so complain.
   LOG(ERROR) << "Unexpected dex PC event in tracing " << PrettyMethod(method) << " " << new_dex_pc;
 }
 
 void Trace::FieldRead(Thread* thread, mirror::Object* this_object,
-                       mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field)
+                       ArtMethod* method, uint32_t dex_pc, ArtField* field)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   UNUSED(thread, this_object, method, dex_pc, field);
   // We're not recorded to listen to this kind of event, so complain.
@@ -776,7 +783,7 @@
 }
 
 void Trace::FieldWritten(Thread* thread, mirror::Object* this_object,
-                          mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field,
+                          ArtMethod* method, uint32_t dex_pc, ArtField* field,
                           const JValue& field_value)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   UNUSED(thread, this_object, method, dex_pc, field, field_value);
@@ -785,7 +792,7 @@
 }
 
 void Trace::MethodEntered(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
-                          mirror::ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
+                          ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
   uint32_t thread_clock_diff = 0;
   uint32_t wall_clock_diff = 0;
   ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
@@ -794,7 +801,7 @@
 }
 
 void Trace::MethodExited(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
-                         mirror::ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED,
+                         ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED,
                          const JValue& return_value ATTRIBUTE_UNUSED) {
   uint32_t thread_clock_diff = 0;
   uint32_t wall_clock_diff = 0;
@@ -804,7 +811,7 @@
 }
 
 void Trace::MethodUnwind(Thread* thread, mirror::Object* this_object ATTRIBUTE_UNUSED,
-                         mirror::ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
+                         ArtMethod* method, uint32_t dex_pc ATTRIBUTE_UNUSED) {
   uint32_t thread_clock_diff = 0;
   uint32_t wall_clock_diff = 0;
   ReadClocks(thread, &thread_clock_diff, &wall_clock_diff);
@@ -818,7 +825,7 @@
   LOG(ERROR) << "Unexpected exception caught event in tracing";
 }
 
-void Trace::BackwardBranch(Thread* /*thread*/, mirror::ArtMethod* method,
+void Trace::BackwardBranch(Thread* /*thread*/, ArtMethod* method,
                            int32_t /*dex_pc_offset*/)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   LOG(ERROR) << "Unexpected backward branch event in tracing" << PrettyMethod(method);
@@ -840,11 +847,12 @@
   }
 }
 
-bool Trace::RegisterMethod(mirror::ArtMethod* method) {
+bool Trace::RegisterMethod(ArtMethod* method) {
   mirror::DexCache* dex_cache = method->GetDexCache();
-  if (dex_cache->GetResolvedMethod(method->GetDexMethodIndex()) != method) {
-    DCHECK(dex_cache->GetResolvedMethod(method->GetDexMethodIndex()) == nullptr);
-    dex_cache->SetResolvedMethod(method->GetDexMethodIndex(), method);
+  auto* resolved_method = dex_cache->GetResolvedMethod(method->GetDexMethodIndex(), sizeof(void*));
+  if (resolved_method != method) {
+    DCHECK(resolved_method == nullptr);
+    dex_cache->SetResolvedMethod(method->GetDexMethodIndex(), method, sizeof(void*));
   }
   if (seen_methods_.find(dex_cache) == seen_methods_.end()) {
     seen_methods_.insert(std::make_pair(dex_cache, new DexIndexBitSet()));
@@ -869,7 +877,7 @@
   return false;
 }
 
-static std::string GetMethodLine(mirror::ArtMethod* method)
+static std::string GetMethodLine(ArtMethod* method)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   return StringPrintf("%p\t%s\t%s\t%s\t%s\n", method,
       PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(), method->GetName(),
@@ -902,7 +910,7 @@
   memcpy(buf_.get() + old_offset, src, src_size);
 }
 
-void Trace::LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
+void Trace::LogMethodTraceEvent(Thread* thread, ArtMethod* method,
                                 instrumentation::Instrumentation::InstrumentationEvent event,
                                 uint32_t thread_clock_diff, uint32_t wall_clock_diff) {
   // Advance cur_offset_ atomically.
@@ -936,11 +944,11 @@
       UNIMPLEMENTED(FATAL) << "Unexpected event: " << event;
   }
 
-  uint32_t method_value = EncodeTraceMethodAndAction(method, action);
+  uint64_t method_value = EncodeTraceMethodAndAction(method, action);
 
   // Write data
   uint8_t* ptr;
-  static constexpr size_t kPacketSize = 14U;  // The maximum size of data in a packet.
+  static constexpr size_t kPacketSize = 18U;  // The maximum size of data in a packet.
   uint8_t stack_buf[kPacketSize];             // Space to store a packet when in streaming mode.
   if (trace_output_mode_ == TraceOutputMode::kStreaming) {
     ptr = stack_buf;
@@ -949,8 +957,8 @@
   }
 
   Append2LE(ptr, thread->GetTid());
-  Append4LE(ptr + 2, method_value);
-  ptr += 6;
+  Append8LE(ptr + 2, method_value);
+  ptr += 10;
 
   if (UseThreadCpuClock()) {
     Append4LE(ptr, thread_clock_diff);
@@ -959,7 +967,7 @@
   if (UseWallClock()) {
     Append4LE(ptr, wall_clock_diff);
   }
-  static_assert(kPacketSize == 2 + 4 + 4 + 4, "Packet size incorrect.");
+  static_assert(kPacketSize == 2 + 8 + 4 + 4, "Packet size incorrect.");
 
   if (trace_output_mode_ == TraceOutputMode::kStreaming) {
     MutexLock mu(Thread::Current(), *streaming_lock_);  // To serialize writing.
@@ -990,19 +998,19 @@
 }
 
 void Trace::GetVisitedMethods(size_t buf_size,
-                              std::set<mirror::ArtMethod*>* visited_methods) {
+                              std::set<ArtMethod*>* visited_methods) {
   uint8_t* ptr = buf_.get() + kTraceHeaderLength;
   uint8_t* end = buf_.get() + buf_size;
 
   while (ptr < end) {
-    uint32_t tmid = ptr[2] | (ptr[3] << 8) | (ptr[4] << 16) | (ptr[5] << 24);
-    mirror::ArtMethod* method = DecodeTraceMethodId(tmid);
+    uint64_t tmid = ReadBytes(ptr + 2, sizeof(tmid));
+    ArtMethod* method = DecodeTraceMethodId(tmid);
     visited_methods->insert(method);
     ptr += GetRecordSize(clock_source_);
   }
 }
 
-void Trace::DumpMethodList(std::ostream& os, const std::set<mirror::ArtMethod*>& visited_methods) {
+void Trace::DumpMethodList(std::ostream& os, const std::set<ArtMethod*>& visited_methods) {
   for (const auto& method : visited_methods) {
     os << GetMethodLine(method);
   }
diff --git a/runtime/trace.h b/runtime/trace.h
index df6d5e7..1539c06 100644
--- a/runtime/trace.h
+++ b/runtime/trace.h
@@ -35,11 +35,11 @@
 namespace art {
 
 namespace mirror {
-  class ArtMethod;
   class DexCache;
 }  // namespace mirror
 
 class ArtField;
+class ArtMethod;
 class Thread;
 
 using DexIndexBitSet = std::bitset<65536>;
@@ -99,38 +99,38 @@
   void MeasureClockOverhead();
   uint32_t GetClockOverheadNanoSeconds();
 
-  void CompareAndUpdateStackTrace(Thread* thread, std::vector<mirror::ArtMethod*>* stack_trace)
+  void CompareAndUpdateStackTrace(Thread* thread, std::vector<ArtMethod*>* stack_trace)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // InstrumentationListener implementation.
   void MethodEntered(Thread* thread, mirror::Object* this_object,
-                     mirror::ArtMethod* method, uint32_t dex_pc)
+                     ArtMethod* method, uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
   void MethodExited(Thread* thread, mirror::Object* this_object,
-                    mirror::ArtMethod* method, uint32_t dex_pc,
+                    ArtMethod* method, uint32_t dex_pc,
                     const JValue& return_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
   void MethodUnwind(Thread* thread, mirror::Object* this_object,
-                    mirror::ArtMethod* method, uint32_t dex_pc)
+                    ArtMethod* method, uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
   void DexPcMoved(Thread* thread, mirror::Object* this_object,
-                  mirror::ArtMethod* method, uint32_t new_dex_pc)
+                  ArtMethod* method, uint32_t new_dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
   void FieldRead(Thread* thread, mirror::Object* this_object,
-                 mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field)
+                 ArtMethod* method, uint32_t dex_pc, ArtField* field)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
   void FieldWritten(Thread* thread, mirror::Object* this_object,
-                    mirror::ArtMethod* method, uint32_t dex_pc, ArtField* field,
+                    ArtMethod* method, uint32_t dex_pc, ArtField* field,
                     const JValue& field_value)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
   void ExceptionCaught(Thread* thread, mirror::Throwable* exception_object)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
-  void BackwardBranch(Thread* thread, mirror::ArtMethod* method, int32_t dex_pc_offset)
+  void BackwardBranch(Thread* thread, ArtMethod* method, int32_t dex_pc_offset)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) OVERRIDE;
   // Reuse an old stack trace if it exists, otherwise allocate a new one.
-  static std::vector<mirror::ArtMethod*>* AllocStackTrace();
+  static std::vector<ArtMethod*>* AllocStackTrace();
   // Clear and store an old stack trace for later use.
-  static void FreeStackTrace(std::vector<mirror::ArtMethod*>* stack_trace);
+  static void FreeStackTrace(std::vector<ArtMethod*>* stack_trace);
   // Save id and name of a thread before it exits.
   static void StoreExitingThreadInfo(Thread* thread);
 
@@ -150,20 +150,20 @@
 
   void ReadClocks(Thread* thread, uint32_t* thread_clock_diff, uint32_t* wall_clock_diff);
 
-  void LogMethodTraceEvent(Thread* thread, mirror::ArtMethod* method,
+  void LogMethodTraceEvent(Thread* thread, ArtMethod* method,
                            instrumentation::Instrumentation::InstrumentationEvent event,
                            uint32_t thread_clock_diff, uint32_t wall_clock_diff)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Methods to output traced methods and threads.
-  void GetVisitedMethods(size_t end_offset, std::set<mirror::ArtMethod*>* visited_methods);
-  void DumpMethodList(std::ostream& os, const std::set<mirror::ArtMethod*>& visited_methods)
+  void GetVisitedMethods(size_t end_offset, std::set<ArtMethod*>* visited_methods);
+  void DumpMethodList(std::ostream& os, const std::set<ArtMethod*>& visited_methods)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void DumpThreadList(std::ostream& os) LOCKS_EXCLUDED(Locks::thread_list_lock_);
 
   // Methods to register seen entitites in streaming mode. The methods return true if the entity
   // is newly discovered.
-  bool RegisterMethod(mirror::ArtMethod* method)
+  bool RegisterMethod(ArtMethod* method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(streaming_lock_);
   bool RegisterThread(Thread* thread)
       EXCLUSIVE_LOCKS_REQUIRED(streaming_lock_);
@@ -183,7 +183,7 @@
   static pthread_t sampling_pthread_;
 
   // Used to remember an unused stack trace to avoid re-allocation during sampling.
-  static std::unique_ptr<std::vector<mirror::ArtMethod*>> temp_stack_trace_;
+  static std::unique_ptr<std::vector<ArtMethod*>> temp_stack_trace_;
 
   // File to write trace data out to, null if direct to ddms.
   std::unique_ptr<File> trace_file_;
diff --git a/runtime/transaction.cc b/runtime/transaction.cc
index ab821d7..d91860b 100644
--- a/runtime/transaction.cc
+++ b/runtime/transaction.cc
@@ -20,6 +20,7 @@
 #include "base/logging.h"
 #include "gc/accounting/card_table-inl.h"
 #include "intern_table.h"
+#include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index aee2c54..8279a26 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -17,10 +17,10 @@
 #include "transaction.h"
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "mirror/array-inl.h"
-#include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 
 namespace art {
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 2671b46..4923342 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -26,10 +26,10 @@
 #include <memory>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/stl_util.h"
 #include "base/unix_file/fd_file.h"
 #include "dex_file-inl.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
 #include "mirror/object-inl.h"
@@ -344,10 +344,13 @@
   return PrettyDescriptor(return_type);
 }
 
-std::string PrettyMethod(mirror::ArtMethod* m, bool with_signature) {
+std::string PrettyMethod(ArtMethod* m, bool with_signature) {
   if (m == nullptr) {
     return "null";
   }
+  if (!m->IsRuntimeMethod()) {
+    m = m->GetInterfaceMethodIfProxy(Runtime::Current()->GetClassLinker()->GetImagePointerSize());
+  }
   std::string result(PrettyDescriptor(m->GetDeclaringClassDescriptor()));
   result += '.';
   result += m->GetName();
@@ -595,7 +598,7 @@
   return descriptor;
 }
 
-std::string JniShortName(mirror::ArtMethod* m) {
+std::string JniShortName(ArtMethod* m) {
   std::string class_name(m->GetDeclaringClassDescriptor());
   // Remove the leading 'L' and trailing ';'...
   CHECK_EQ(class_name[0], 'L') << class_name;
@@ -613,7 +616,7 @@
   return short_name;
 }
 
-std::string JniLongName(mirror::ArtMethod* m) {
+std::string JniLongName(ArtMethod* m) {
   std::string long_name;
   long_name += JniShortName(m);
   long_name += "__";
@@ -1088,7 +1091,7 @@
 #endif
 
 void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix,
-    mirror::ArtMethod* current_method, void* ucontext_ptr) {
+    ArtMethod* current_method, void* ucontext_ptr) {
 #if __linux__
   // b/18119146
   if (RUNNING_ON_VALGRIND != 0) {
diff --git a/runtime/utils.h b/runtime/utils.h
index e7532e1..1ef98e7 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -34,10 +34,10 @@
 namespace art {
 
 class ArtField;
+class ArtMethod;
 class DexFile;
 
 namespace mirror {
-class ArtMethod;
 class Class;
 class Object;
 class String;
@@ -125,7 +125,7 @@
 
 // Returns a human-readable signature for 'm'. Something like "a.b.C.m" or
 // "a.b.C.m(II)V" (depending on the value of 'with_signature').
-std::string PrettyMethod(mirror::ArtMethod* m, bool with_signature = true)
+std::string PrettyMethod(ArtMethod* m, bool with_signature = true)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature = true);
 
@@ -181,10 +181,10 @@
 bool IsValidMemberName(const char* s);
 
 // Returns the JNI native function name for the non-overloaded method 'm'.
-std::string JniShortName(mirror::ArtMethod* m)
+std::string JniShortName(ArtMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 // Returns the JNI native function name for the overloaded method 'm'.
-std::string JniLongName(mirror::ArtMethod* m)
+std::string JniLongName(ArtMethod* m)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 bool ReadFileToString(const std::string& file_name, std::string* result);
@@ -221,7 +221,7 @@
 
 // Dumps the native stack for thread 'tid' to 'os'.
 void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix = "",
-    mirror::ArtMethod* current_method = nullptr, void* ucontext = nullptr)
+    ArtMethod* current_method = nullptr, void* ucontext = nullptr)
     NO_THREAD_SAFETY_ANALYSIS;
 
 // Dumps the kernel stack for thread 'tid' to 'os'. Note that this is only available on linux-x86.
@@ -320,6 +320,9 @@
   return ((bitmap[idx / kBitsPerByte] >> (idx % kBitsPerByte)) & 0x01) != 0;
 }
 
+static inline constexpr bool ValidPointerSize(size_t pointer_size) {
+  return pointer_size == 4 || pointer_size == 8;
+}
 
 }  // namespace art
 
diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc
index 8a7f805..66e38b1 100644
--- a/runtime/utils_test.cc
+++ b/runtime/utils_test.cc
@@ -185,19 +185,19 @@
   ScopedObjectAccess soa(Thread::Current());
   mirror::Class* c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;");
   ASSERT_TRUE(c != nullptr);
-  mirror::ArtMethod* m;
+  ArtMethod* m;
 
-  m = c->FindVirtualMethod("charAt", "(I)C");
+  m = c->FindVirtualMethod("charAt", "(I)C", sizeof(void*));
   ASSERT_TRUE(m != nullptr);
   EXPECT_EQ("Java_java_lang_String_charAt", JniShortName(m));
   EXPECT_EQ("Java_java_lang_String_charAt__I", JniLongName(m));
 
-  m = c->FindVirtualMethod("indexOf", "(Ljava/lang/String;I)I");
+  m = c->FindVirtualMethod("indexOf", "(Ljava/lang/String;I)I", sizeof(void*));
   ASSERT_TRUE(m != nullptr);
   EXPECT_EQ("Java_java_lang_String_indexOf", JniShortName(m));
   EXPECT_EQ("Java_java_lang_String_indexOf__Ljava_lang_String_2I", JniLongName(m));
 
-  m = c->FindDirectMethod("copyValueOf", "([CII)Ljava/lang/String;");
+  m = c->FindDirectMethod("copyValueOf", "([CII)Ljava/lang/String;", sizeof(void*));
   ASSERT_TRUE(m != nullptr);
   EXPECT_EQ("Java_java_lang_String_copyValueOf", JniShortName(m));
   EXPECT_EQ("Java_java_lang_String_copyValueOf___3CII", JniLongName(m));
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index b08883e..f25e4ee 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -19,6 +19,7 @@
 #include <iostream>
 
 #include "art_field-inl.h"
+#include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/mutex-inl.h"
 #include "base/time_utils.h"
@@ -32,7 +33,6 @@
 #include "indenter.h"
 #include "intern_table.h"
 #include "leb128.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
@@ -115,15 +115,13 @@
 }
 
 MethodVerifier::FailureKind MethodVerifier::VerifyMethod(
-    mirror::ArtMethod* method, bool allow_soft_failures, std::string* error ATTRIBUTE_UNUSED) {
-  Thread* self = Thread::Current();
-  StackHandleScope<3> hs(self);
+    ArtMethod* method, bool allow_soft_failures, std::string* error ATTRIBUTE_UNUSED) {
+  StackHandleScope<2> hs(Thread::Current());
   mirror::Class* klass = method->GetDeclaringClass();
   auto h_dex_cache(hs.NewHandle(klass->GetDexCache()));
   auto h_class_loader(hs.NewHandle(klass->GetClassLoader()));
-  auto h_method = hs.NewHandle(method);
-  return VerifyMethod(self, method->GetDexMethodIndex(), method->GetDexFile(), h_dex_cache,
-                      h_class_loader, klass->GetClassDef(), method->GetCodeItem(), h_method,
+  return VerifyMethod(hs.Self(), method->GetDexMethodIndex(), method->GetDexFile(), h_dex_cache,
+                      h_class_loader, klass->GetClassDef(), method->GetCodeItem(), method,
                       method->GetAccessFlags(), allow_soft_failures, false);
 }
 
@@ -162,7 +160,8 @@
   StackHandleScope<2> hs(self);
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
-  return VerifyClass(self, &dex_file, dex_cache, class_loader, class_def, allow_soft_failures, error);
+  return VerifyClass(
+      self, &dex_file, dex_cache, class_loader, class_def, allow_soft_failures, error);
 }
 
 MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self,
@@ -197,16 +196,16 @@
     }
     previous_direct_method_idx = method_idx;
     InvokeType type = it.GetMethodInvokeType(*class_def);
-    mirror::ArtMethod* method =
-        linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader,
-                              NullHandle<mirror::ArtMethod>(), type);
+    ArtMethod* method = linker->ResolveMethod(
+        *dex_file, method_idx, dex_cache, class_loader, nullptr, type);
     if (method == nullptr) {
       DCHECK(self->IsExceptionPending());
       // We couldn't resolve the method, but continue regardless.
       self->ClearException();
+    } else {
+      DCHECK(method->GetDeclaringClassUnchecked() != nullptr) << type;
     }
     StackHandleScope<1> hs(self);
-    Handle<mirror::ArtMethod> h_method(hs.NewHandle(method));
     MethodVerifier::FailureKind result = VerifyMethod(self,
                                                       method_idx,
                                                       dex_file,
@@ -214,10 +213,7 @@
                                                       class_loader,
                                                       class_def,
                                                       it.GetMethodCodeItem(),
-                                                      h_method,
-                                                      it.GetMethodAccessFlags(),
-                                                      allow_soft_failures,
-                                                      false);
+        method, it.GetMethodAccessFlags(), allow_soft_failures, false);
     if (result != kNoFailure) {
       if (result == kHardFailure) {
         hard_fail = true;
@@ -245,16 +241,14 @@
     }
     previous_virtual_method_idx = method_idx;
     InvokeType type = it.GetMethodInvokeType(*class_def);
-    mirror::ArtMethod* method =
-        linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader,
-                              NullHandle<mirror::ArtMethod>(), type);
+    ArtMethod* method = linker->ResolveMethod(
+        *dex_file, method_idx, dex_cache, class_loader, nullptr, type);
     if (method == nullptr) {
       DCHECK(self->IsExceptionPending());
       // We couldn't resolve the method, but continue regardless.
       self->ClearException();
     }
     StackHandleScope<1> hs(self);
-    Handle<mirror::ArtMethod> h_method(hs.NewHandle(method));
     MethodVerifier::FailureKind result = VerifyMethod(self,
                                                       method_idx,
                                                       dex_file,
@@ -262,10 +256,7 @@
                                                       class_loader,
                                                       class_def,
                                                       it.GetMethodCodeItem(),
-                                                      h_method,
-                                                      it.GetMethodAccessFlags(),
-                                                      allow_soft_failures,
-                                                      false);
+        method, it.GetMethodAccessFlags(), allow_soft_failures, false);
     if (result != kNoFailure) {
       if (result == kHardFailure) {
         hard_fail = true;
@@ -305,7 +296,7 @@
                                                          Handle<mirror::ClassLoader> class_loader,
                                                          const DexFile::ClassDef* class_def,
                                                          const DexFile::CodeItem* code_item,
-                                                         Handle<mirror::ArtMethod> method,
+                                                         ArtMethod* method,
                                                          uint32_t method_access_flags,
                                                          bool allow_soft_failures,
                                                          bool need_precise_constants) {
@@ -355,7 +346,7 @@
                                          Handle<mirror::ClassLoader> class_loader,
                                          const DexFile::ClassDef* class_def,
                                          const DexFile::CodeItem* code_item,
-                                         Handle<mirror::ArtMethod> method,
+                                         ArtMethod* method,
                                          uint32_t method_access_flags) {
   MethodVerifier* verifier = new MethodVerifier(self, dex_file, dex_cache, class_loader,
                                                 class_def, code_item, dex_method_idx, method,
@@ -379,7 +370,7 @@
                                Handle<mirror::ClassLoader> class_loader,
                                const DexFile::ClassDef* class_def,
                                const DexFile::CodeItem* code_item, uint32_t dex_method_idx,
-                               Handle<mirror::ArtMethod> method, uint32_t method_access_flags,
+                               ArtMethod* method, uint32_t method_access_flags,
                                bool can_load_classes, bool allow_soft_failures,
                                bool need_precise_constants, bool verify_to_dump,
                                bool allow_thread_suspension)
@@ -418,15 +409,13 @@
   STLDeleteElements(&failure_messages_);
 }
 
-void MethodVerifier::FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc,
+void MethodVerifier::FindLocksAtDexPc(ArtMethod* m, uint32_t dex_pc,
                                       std::vector<uint32_t>* monitor_enter_dex_pcs) {
-  Thread* self = Thread::Current();
-  StackHandleScope<3> hs(self);
+  StackHandleScope<2> hs(Thread::Current());
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache()));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader()));
-  Handle<mirror::ArtMethod> method(hs.NewHandle(m));
-  MethodVerifier verifier(self, m->GetDexFile(), dex_cache, class_loader, &m->GetClassDef(),
-                          m->GetCodeItem(), m->GetDexMethodIndex(), method, m->GetAccessFlags(),
+  MethodVerifier verifier(hs.Self(), m->GetDexFile(), dex_cache, class_loader, &m->GetClassDef(),
+                          m->GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(),
                           false, true, false, false);
   verifier.interesting_dex_pc_ = dex_pc;
   verifier.monitor_enter_dex_pcs_ = monitor_enter_dex_pcs;
@@ -465,16 +454,13 @@
   Verify();
 }
 
-ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m,
-                                                           uint32_t dex_pc) {
-  Thread* self = Thread::Current();
-  StackHandleScope<3> hs(self);
+ArtField* MethodVerifier::FindAccessedFieldAtDexPc(ArtMethod* m, uint32_t dex_pc) {
+  StackHandleScope<2> hs(Thread::Current());
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache()));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader()));
-  Handle<mirror::ArtMethod> method(hs.NewHandle(m));
-  MethodVerifier verifier(self, m->GetDexFile(), dex_cache, class_loader, &m->GetClassDef(),
-                          m->GetCodeItem(), m->GetDexMethodIndex(), method, m->GetAccessFlags(),
-                          true, true, false, true);
+  MethodVerifier verifier(hs.Self(), m->GetDexFile(), dex_cache, class_loader, &m->GetClassDef(),
+                          m->GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), true,
+                          true, false, true);
   return verifier.FindAccessedFieldAtDexPc(dex_pc);
 }
 
@@ -497,20 +483,17 @@
   return GetQuickFieldAccess(inst, register_line);
 }
 
-mirror::ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(mirror::ArtMethod* m,
-                                                            uint32_t dex_pc) {
-  Thread* self = Thread::Current();
-  StackHandleScope<3> hs(self);
+ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(ArtMethod* m, uint32_t dex_pc) {
+  StackHandleScope<2> hs(Thread::Current());
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache()));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader()));
-  Handle<mirror::ArtMethod> method(hs.NewHandle(m));
-  MethodVerifier verifier(self, m->GetDexFile(), dex_cache, class_loader, &m->GetClassDef(),
-                          m->GetCodeItem(), m->GetDexMethodIndex(), method, m->GetAccessFlags(),
-                          true, true, false, true);
+  MethodVerifier verifier(hs.Self(), m->GetDexFile(), dex_cache, class_loader, &m->GetClassDef(),
+                          m->GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), true,
+                          true, false, true);
   return verifier.FindInvokedMethodAtDexPc(dex_pc);
 }
 
-mirror::ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(uint32_t dex_pc) {
+ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(uint32_t dex_pc) {
   CHECK(code_item_ != nullptr);  // This only makes sense for methods with code.
 
   // Strictly speaking, we ought to be able to get away with doing a subset of the full method
@@ -530,14 +513,13 @@
   return GetQuickInvokedMethod(inst, register_line, is_range, false);
 }
 
-SafeMap<uint32_t, std::set<uint32_t>> MethodVerifier::FindStringInitMap(mirror::ArtMethod* m) {
+SafeMap<uint32_t, std::set<uint32_t>> MethodVerifier::FindStringInitMap(ArtMethod* m) {
   Thread* self = Thread::Current();
-  StackHandleScope<3> hs(self);
+  StackHandleScope<2> hs(self);
   Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache()));
   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader()));
-  Handle<mirror::ArtMethod> method(hs.NewHandle(m));
   MethodVerifier verifier(self, m->GetDexFile(), dex_cache, class_loader, &m->GetClassDef(),
-                          m->GetCodeItem(), m->GetDexMethodIndex(), method, m->GetAccessFlags(),
+                          m->GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(),
                           true, true, false, true);
   return verifier.FindStringInitMap();
 }
@@ -2374,15 +2356,13 @@
                        inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
       bool is_super = (inst->Opcode() == Instruction::INVOKE_SUPER ||
                        inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
-      mirror::ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_VIRTUAL, is_range,
-                                                              is_super);
+      ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_VIRTUAL, is_range, is_super);
       const RegType* return_type = nullptr;
       if (called_method != nullptr) {
         StackHandleScope<1> hs(self_);
-        Handle<mirror::ArtMethod> h_called_method(hs.NewHandle(called_method));
-        mirror::Class* return_type_class = h_called_method->GetReturnType(can_load_classes_);
+        mirror::Class* return_type_class = called_method->GetReturnType(can_load_classes_);
         if (return_type_class != nullptr) {
-          return_type = &reg_types_.FromClass(h_called_method->GetReturnTypeDescriptor(),
+          return_type = &reg_types_.FromClass(called_method->GetReturnTypeDescriptor(),
                                               return_type_class,
                                               return_type_class->CannotBeAssignedFromOtherTypes());
         } else {
@@ -2408,8 +2388,7 @@
     case Instruction::INVOKE_DIRECT:
     case Instruction::INVOKE_DIRECT_RANGE: {
       bool is_range = (inst->Opcode() == Instruction::INVOKE_DIRECT_RANGE);
-      mirror::ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_DIRECT,
-                                                                   is_range, false);
+      ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_DIRECT, is_range, false);
       const char* return_type_descriptor;
       bool is_constructor;
       const RegType* return_type = nullptr;
@@ -2423,8 +2402,7 @@
         is_constructor = called_method->IsConstructor();
         return_type_descriptor = called_method->GetReturnTypeDescriptor();
         StackHandleScope<1> hs(self_);
-        Handle<mirror::ArtMethod> h_called_method(hs.NewHandle(called_method));
-        mirror::Class* return_type_class = h_called_method->GetReturnType(can_load_classes_);
+        mirror::Class* return_type_class = called_method->GetReturnType(can_load_classes_);
         if (return_type_class != nullptr) {
           return_type = &reg_types_.FromClass(return_type_descriptor,
                                               return_type_class,
@@ -2490,10 +2468,7 @@
     case Instruction::INVOKE_STATIC:
     case Instruction::INVOKE_STATIC_RANGE: {
         bool is_range = (inst->Opcode() == Instruction::INVOKE_STATIC_RANGE);
-        mirror::ArtMethod* called_method = VerifyInvocationArgs(inst,
-                                                                     METHOD_STATIC,
-                                                                     is_range,
-                                                                     false);
+        ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_STATIC, is_range, false);
         const char* descriptor;
         if (called_method == nullptr) {
           uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
@@ -2515,10 +2490,7 @@
     case Instruction::INVOKE_INTERFACE:
     case Instruction::INVOKE_INTERFACE_RANGE: {
       bool is_range =  (inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE);
-      mirror::ArtMethod* abs_method = VerifyInvocationArgs(inst,
-                                                                METHOD_INTERFACE,
-                                                                is_range,
-                                                                false);
+      ArtMethod* abs_method = VerifyInvocationArgs(inst, METHOD_INTERFACE, is_range, false);
       if (abs_method != nullptr) {
         mirror::Class* called_interface = abs_method->GetDeclaringClass();
         if (!called_interface->IsInterface() && !called_interface->IsObjectClass()) {
@@ -2843,7 +2815,7 @@
     case Instruction::INVOKE_VIRTUAL_QUICK:
     case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
       bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
-      mirror::ArtMethod* called_method = VerifyInvokeVirtualQuickArgs(inst, is_range);
+      ArtMethod* called_method = VerifyInvokeVirtualQuickArgs(inst, is_range);
       if (called_method != nullptr) {
         const char* descriptor = called_method->GetReturnTypeDescriptor();
         const RegType& return_type = reg_types_.FromDescriptor(GetClassLoader(), descriptor, false);
@@ -3194,8 +3166,8 @@
   return *common_super;
 }
 
-mirror::ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_method_idx,
-                                                               MethodType method_type) {
+ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(
+    uint32_t dex_method_idx, MethodType method_type) {
   const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx);
   const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_);
   if (klass_type.IsConflict()) {
@@ -3209,26 +3181,28 @@
   }
   mirror::Class* klass = klass_type.GetClass();
   const RegType& referrer = GetDeclaringClass();
-  mirror::ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx);
+  auto* cl = Runtime::Current()->GetClassLinker();
+  auto pointer_size = cl->GetImagePointerSize();
+  ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx, pointer_size);
   if (res_method == nullptr) {
     const char* name = dex_file_->GetMethodName(method_id);
     const Signature signature = dex_file_->GetMethodSignature(method_id);
 
     if (method_type == METHOD_DIRECT || method_type == METHOD_STATIC) {
-      res_method = klass->FindDirectMethod(name, signature);
+      res_method = klass->FindDirectMethod(name, signature, pointer_size);
     } else if (method_type == METHOD_INTERFACE) {
-      res_method = klass->FindInterfaceMethod(name, signature);
+      res_method = klass->FindInterfaceMethod(name, signature, pointer_size);
     } else {
-      res_method = klass->FindVirtualMethod(name, signature);
+      res_method = klass->FindVirtualMethod(name, signature, pointer_size);
     }
     if (res_method != nullptr) {
-      dex_cache_->SetResolvedMethod(dex_method_idx, res_method);
+      dex_cache_->SetResolvedMethod(dex_method_idx, res_method, pointer_size);
     } else {
       // If a virtual or interface method wasn't found with the expected type, look in
       // the direct methods. This can happen when the wrong invoke type is used or when
       // a class has changed, and will be flagged as an error in later checks.
       if (method_type == METHOD_INTERFACE || method_type == METHOD_VIRTUAL) {
-        res_method = klass->FindDirectMethod(name, signature);
+        res_method = klass->FindDirectMethod(name, signature, pointer_size);
       }
       if (res_method == nullptr) {
         Fail(VERIFY_ERROR_NO_METHOD) << "couldn't find method "
@@ -3287,10 +3261,8 @@
 }
 
 template <class T>
-mirror::ArtMethod* MethodVerifier::VerifyInvocationArgsFromIterator(T* it, const Instruction* inst,
-                                                                    MethodType method_type,
-                                                                    bool is_range,
-                                                                    mirror::ArtMethod* res_method) {
+ArtMethod* MethodVerifier::VerifyInvocationArgsFromIterator(
+    T* it, const Instruction* inst, MethodType method_type, bool is_range, ArtMethod* res_method) {
   // We use vAA as our expected arg count, rather than res_method->insSize, because we need to
   // match the call to the signature. Also, we might be calling through an abstract method
   // definition (which doesn't have register count values).
@@ -3420,7 +3392,7 @@
 
 class MethodParamListDescriptorIterator {
  public:
-  explicit MethodParamListDescriptorIterator(mirror::ArtMethod* res_method) :
+  explicit MethodParamListDescriptorIterator(ArtMethod* res_method) :
       res_method_(res_method), pos_(0), params_(res_method->GetParameterTypeList()),
       params_size_(params_ == nullptr ? 0 : params_->Size()) {
   }
@@ -3438,21 +3410,19 @@
   }
 
  private:
-  mirror::ArtMethod* res_method_;
+  ArtMethod* res_method_;
   size_t pos_;
   const DexFile::TypeList* params_;
   const size_t params_size_;
 };
 
-mirror::ArtMethod* MethodVerifier::VerifyInvocationArgs(const Instruction* inst,
-                                                             MethodType method_type,
-                                                             bool is_range,
-                                                             bool is_super) {
+ArtMethod* MethodVerifier::VerifyInvocationArgs(
+    const Instruction* inst, MethodType method_type, bool is_range, bool is_super) {
   // Resolve the method. This could be an abstract or concrete method depending on what sort of call
   // we're making.
   const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
 
-  mirror::ArtMethod* res_method = ResolveMethodAndCheckAccess(method_idx, method_type);
+  ArtMethod* res_method = ResolveMethodAndCheckAccess(method_idx, method_type);
   if (res_method == nullptr) {  // error or class is unresolved
     // Check what we can statically.
     if (!have_pending_hard_failure_) {
@@ -3489,9 +3459,8 @@
                                                                              is_range, res_method);
 }
 
-mirror::ArtMethod* MethodVerifier::GetQuickInvokedMethod(const Instruction* inst,
-                                                         RegisterLine* reg_line, bool is_range,
-                                                         bool allow_failure) {
+ArtMethod* MethodVerifier::GetQuickInvokedMethod(const Instruction* inst, RegisterLine* reg_line,
+                                                 bool is_range, bool allow_failure) {
   if (is_range) {
     DCHECK_EQ(inst->Opcode(), Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
   } else {
@@ -3521,13 +3490,15 @@
     return nullptr;
   }
   uint16_t vtable_index = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
+  auto* cl = Runtime::Current()->GetClassLinker();
+  auto pointer_size = cl->GetImagePointerSize();
   if (static_cast<int32_t>(vtable_index) >= dispatch_class->GetVTableLength()) {
     FailOrAbort(this, allow_failure,
                 "Receiver class has not enough vtable slots for quickened invoke at ",
                 work_insn_idx_);
     return nullptr;
   }
-  mirror::ArtMethod* res_method = dispatch_class->GetVTableEntry(vtable_index);
+  ArtMethod* res_method = dispatch_class->GetVTableEntry(vtable_index, pointer_size);
   if (self_->IsExceptionPending()) {
     FailOrAbort(this, allow_failure, "Unexpected exception pending for quickened invoke at ",
                 work_insn_idx_);
@@ -3536,12 +3507,11 @@
   return res_method;
 }
 
-mirror::ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instruction* inst,
-                                                                bool is_range) {
+ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instruction* inst, bool is_range) {
   DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_)
       << PrettyMethod(dex_method_idx_, *dex_file_, true) << "@" << work_insn_idx_;
 
-  mirror::ArtMethod* res_method = GetQuickInvokedMethod(inst, work_line_.get(), is_range, false);
+  ArtMethod* res_method = GetQuickInvokedMethod(inst, work_line_.get(), is_range, false);
   if (res_method == nullptr) {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer method from " << inst->Name();
     return nullptr;
@@ -4247,7 +4217,7 @@
 
 const RegType& MethodVerifier::GetMethodReturnType() {
   if (return_type_ == nullptr) {
-    if (mirror_method_.Get() != nullptr) {
+    if (mirror_method_ != nullptr) {
       mirror::Class* return_type_class = mirror_method_->GetReturnType(can_load_classes_);
       if (return_type_class != nullptr) {
         return_type_ = &reg_types_.FromClass(mirror_method_->GetReturnTypeDescriptor(),
@@ -4274,7 +4244,7 @@
     const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
     const char* descriptor
         = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_));
-    if (mirror_method_.Get() != nullptr) {
+    if (mirror_method_ != nullptr) {
       mirror::Class* klass = mirror_method_->GetDeclaringClass();
       declaring_class_ = &reg_types_.FromClass(descriptor, klass,
                                                klass->CannotBeAssignedFromOtherTypes());
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 452d1dd..873b8ab 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -152,12 +152,11 @@
                                              Handle<mirror::DexCache> dex_cache,
                                              Handle<mirror::ClassLoader> class_loader,
                                              const DexFile::ClassDef* class_def,
-                                             const DexFile::CodeItem* code_item,
-                                             Handle<mirror::ArtMethod> method,
+                                             const DexFile::CodeItem* code_item, ArtMethod* method,
                                              uint32_t method_access_flags)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static FailureKind VerifyMethod(mirror::ArtMethod* method, bool allow_soft_failures,
+  static FailureKind VerifyMethod(ArtMethod* method, bool allow_soft_failures,
                                   std::string* error) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   uint8_t EncodePcToReferenceMapData() const;
@@ -185,21 +184,21 @@
 
   // Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding
   // to the locks held at 'dex_pc' in method 'm'.
-  static void FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc,
+  static void FindLocksAtDexPc(ArtMethod* m, uint32_t dex_pc,
                                std::vector<uint32_t>* monitor_enter_dex_pcs)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns the accessed field corresponding to the quick instruction's field
   // offset at 'dex_pc' in method 'm'.
-  static ArtField* FindAccessedFieldAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc)
+  static ArtField* FindAccessedFieldAtDexPc(ArtMethod* m, uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns the invoked method corresponding to the quick instruction's vtable
   // index at 'dex_pc' in method 'm'.
-  static mirror::ArtMethod* FindInvokedMethodAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc)
+  static ArtMethod* FindInvokedMethodAtDexPc(ArtMethod* m, uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static SafeMap<uint32_t, std::set<uint32_t>> FindStringInitMap(mirror::ArtMethod* m)
+  static SafeMap<uint32_t, std::set<uint32_t>> FindStringInitMap(ArtMethod* m)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void Init() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -212,7 +211,7 @@
   MethodVerifier(Thread* self, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache,
                  Handle<mirror::ClassLoader> class_loader, const DexFile::ClassDef* class_def,
                  const DexFile::CodeItem* code_item, uint32_t method_idx,
-                 Handle<mirror::ArtMethod> method,
+                 ArtMethod* method,
                  uint32_t access_flags, bool can_load_classes, bool allow_soft_failures,
                  bool need_precise_constants, bool allow_thread_suspension)
           SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
@@ -248,7 +247,7 @@
   const RegType& ResolveCheckedClass(uint32_t class_idx)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   // Returns the method of a quick invoke or null if it cannot be found.
-  mirror::ArtMethod* GetQuickInvokedMethod(const Instruction* inst, RegisterLine* reg_line,
+  ArtMethod* GetQuickInvokedMethod(const Instruction* inst, RegisterLine* reg_line,
                                            bool is_range, bool allow_failure)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   // Returns the access field of a quick field access (iget/iput-quick) or null
@@ -275,7 +274,7 @@
   MethodVerifier(Thread* self, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache,
                  Handle<mirror::ClassLoader> class_loader, const DexFile::ClassDef* class_def,
                  const DexFile::CodeItem* code_item, uint32_t method_idx,
-                 Handle<mirror::ArtMethod> method, uint32_t access_flags,
+                 ArtMethod* method, uint32_t access_flags,
                  bool can_load_classes, bool allow_soft_failures, bool need_precise_constants,
                  bool verify_to_dump, bool allow_thread_suspension)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -302,7 +301,7 @@
                                   Handle<mirror::ClassLoader> class_loader,
                                   const DexFile::ClassDef* class_def_idx,
                                   const DexFile::CodeItem* code_item,
-                                  Handle<mirror::ArtMethod> method, uint32_t method_access_flags,
+                                  ArtMethod* method, uint32_t method_access_flags,
                                   bool allow_soft_failures, bool need_precise_constants)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -311,7 +310,7 @@
   ArtField* FindAccessedFieldAtDexPc(uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtMethod* FindInvokedMethodAtDexPc(uint32_t dex_pc)
+  ArtMethod* FindInvokedMethodAtDexPc(uint32_t dex_pc)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   SafeMap<uint32_t, std::set<uint32_t>>& FindStringInitMap()
@@ -573,7 +572,7 @@
    * the referrer can access the resolved method.
    * Does not throw exceptions.
    */
-  mirror::ArtMethod* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type)
+  ArtMethod* ResolveMethodAndCheckAccess(uint32_t method_idx, MethodType method_type)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   /*
@@ -598,7 +597,7 @@
    * Returns the resolved method on success, null on failure (with *failure
    * set appropriately).
    */
-  mirror::ArtMethod* VerifyInvocationArgs(const Instruction* inst,
+  ArtMethod* VerifyInvocationArgs(const Instruction* inst,
                                           MethodType method_type,
                                           bool is_range, bool is_super)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -610,12 +609,12 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   template <class T>
-  mirror::ArtMethod* VerifyInvocationArgsFromIterator(T* it, const Instruction* inst,
+  ArtMethod* VerifyInvocationArgsFromIterator(T* it, const Instruction* inst,
                                                       MethodType method_type, bool is_range,
-                                                      mirror::ArtMethod* res_method)
+                                                      ArtMethod* res_method)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  mirror::ArtMethod* VerifyInvokeVirtualQuickArgs(const Instruction* inst, bool is_range)
+  ArtMethod* VerifyInvokeVirtualQuickArgs(const Instruction* inst, bool is_range)
   SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   /*
@@ -680,7 +679,7 @@
 
   const uint32_t dex_method_idx_;  // The method we're working on.
   // Its object representation if known.
-  Handle<mirror::ArtMethod> mirror_method_ GUARDED_BY(Locks::mutator_lock_);
+  ArtMethod* mirror_method_ GUARDED_BY(Locks::mutator_lock_);
   const uint32_t method_access_flags_;  // Method's access flags.
   const RegType* return_type_;  // Lazily computed return type of the method.
   const DexFile* const dex_file_;  // The dex file containing the method.
diff --git a/runtime/verify_object-inl.h b/runtime/verify_object-inl.h
index 39df375..f7a8249 100644
--- a/runtime/verify_object-inl.h
+++ b/runtime/verify_object-inl.h
@@ -20,7 +20,6 @@
 #include "verify_object.h"
 
 #include "gc/heap.h"
-#include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 
 namespace art {
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 2843806..3dbfe1b 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -22,6 +22,7 @@
 
 #include "base/logging.h"
 #include "mirror/class.h"
+#include "mirror/throwable.h"
 #include "ScopedLocalRef.h"
 #include "scoped_thread_state_change.h"
 #include "thread-inl.h"
@@ -41,7 +42,6 @@
 jclass WellKnownClasses::java_lang_Object;
 jclass WellKnownClasses::java_lang_OutOfMemoryError;
 jclass WellKnownClasses::java_lang_reflect_AbstractMethod;
-jclass WellKnownClasses::java_lang_reflect_ArtMethod;
 jclass WellKnownClasses::java_lang_reflect_Constructor;
 jclass WellKnownClasses::java_lang_reflect_Field;
 jclass WellKnownClasses::java_lang_reflect_Method;
@@ -165,11 +165,13 @@
 
 static jfieldID CacheField(JNIEnv* env, jclass c, bool is_static,
                            const char* name, const char* signature) {
-  jfieldID fid = (is_static ?
-                  env->GetStaticFieldID(c, name, signature) :
-                  env->GetFieldID(c, name, signature));
+  jfieldID fid = is_static ? env->GetStaticFieldID(c, name, signature) :
+      env->GetFieldID(c, name, signature);
   if (fid == nullptr) {
     ScopedObjectAccess soa(env);
+    if (soa.Self()->IsExceptionPending()) {
+      LOG(INTERNAL_FATAL) << soa.Self()->GetException()->Dump() << '\n';
+    }
     std::ostringstream os;
     WellKnownClasses::ToClass(c)->DumpClass(os, mirror::Class::kDumpClassFullDetail);
     LOG(FATAL) << "Couldn't find field \"" << name << "\" with signature \"" << signature << "\": "
@@ -180,11 +182,13 @@
 
 jmethodID CacheMethod(JNIEnv* env, jclass c, bool is_static,
                       const char* name, const char* signature) {
-  jmethodID mid = (is_static ?
-                   env->GetStaticMethodID(c, name, signature) :
-                   env->GetMethodID(c, name, signature));
+  jmethodID mid = is_static ? env->GetStaticMethodID(c, name, signature) :
+      env->GetMethodID(c, name, signature);
   if (mid == nullptr) {
     ScopedObjectAccess soa(env);
+    if (soa.Self()->IsExceptionPending()) {
+      LOG(INTERNAL_FATAL) << soa.Self()->GetException()->Dump() << '\n';
+    }
     std::ostringstream os;
     WellKnownClasses::ToClass(c)->DumpClass(os, mirror::Class::kDumpClassFullDetail);
     LOG(FATAL) << "Couldn't find method \"" << name << "\" with signature \"" << signature << "\": "
@@ -213,7 +217,6 @@
   java_lang_OutOfMemoryError = CacheClass(env, "java/lang/OutOfMemoryError");
   java_lang_Error = CacheClass(env, "java/lang/Error");
   java_lang_reflect_AbstractMethod = CacheClass(env, "java/lang/reflect/AbstractMethod");
-  java_lang_reflect_ArtMethod = CacheClass(env, "java/lang/reflect/ArtMethod");
   java_lang_reflect_Constructor = CacheClass(env, "java/lang/reflect/Constructor");
   java_lang_reflect_Field = CacheClass(env, "java/lang/reflect/Field");
   java_lang_reflect_Method = CacheClass(env, "java/lang/reflect/Method");
@@ -334,7 +337,7 @@
   java_lang_Throwable_stackTrace = CacheField(env, java_lang_Throwable, false, "stackTrace", "[Ljava/lang/StackTraceElement;");
   java_lang_Throwable_stackState = CacheField(env, java_lang_Throwable, false, "stackState", "Ljava/lang/Object;");
   java_lang_Throwable_suppressedExceptions = CacheField(env, java_lang_Throwable, false, "suppressedExceptions", "Ljava/util/List;");
-  java_lang_reflect_AbstractMethod_artMethod = CacheField(env, java_lang_reflect_AbstractMethod, false, "artMethod", "Ljava/lang/reflect/ArtMethod;");
+  java_lang_reflect_AbstractMethod_artMethod = CacheField(env, java_lang_reflect_AbstractMethod, false, "artMethod", "J");
   java_lang_reflect_Proxy_h = CacheField(env, java_lang_reflect_Proxy, false, "h", "Ljava/lang/reflect/InvocationHandler;");
   java_nio_DirectByteBuffer_capacity = CacheField(env, java_nio_DirectByteBuffer, false, "capacity", "I");
   java_nio_DirectByteBuffer_effectiveDirectAddress = CacheField(env, java_nio_DirectByteBuffer, false, "effectiveDirectAddress", "J");
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index acb2656..d25d1c3 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -53,7 +53,6 @@
   static jclass java_lang_Object;
   static jclass java_lang_OutOfMemoryError;
   static jclass java_lang_reflect_AbstractMethod;
-  static jclass java_lang_reflect_ArtMethod;
   static jclass java_lang_reflect_Constructor;
   static jclass java_lang_reflect_Field;
   static jclass java_lang_reflect_Method;
diff --git a/test/004-ReferenceMap/stack_walk_refmap_jni.cc b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
index 76ef4a9..e626e48 100644
--- a/test/004-ReferenceMap/stack_walk_refmap_jni.cc
+++ b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
@@ -36,7 +36,7 @@
     if (CheckReferenceMapVisitor::VisitFrame()) {
       return true;
     }
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     std::string m_name(m->GetName());
 
     // Given the method name and the number of times the method has been called,
diff --git a/test/004-StackWalk/stack_walk_jni.cc b/test/004-StackWalk/stack_walk_jni.cc
index 97afe1c..6b15514 100644
--- a/test/004-StackWalk/stack_walk_jni.cc
+++ b/test/004-StackWalk/stack_walk_jni.cc
@@ -36,7 +36,7 @@
     if (CheckReferenceMapVisitor::VisitFrame()) {
       return true;
     }
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     StringPiece m_name(m->GetName());
 
     // Given the method name and the number of times the method has been called,
diff --git a/test/004-UnsafeTest/unsafe_test.cc b/test/004-UnsafeTest/unsafe_test.cc
index ca0e39e..3b0cf23 100644
--- a/test/004-UnsafeTest/unsafe_test.cc
+++ b/test/004-UnsafeTest/unsafe_test.cc
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
+#include "art_method-inl.h"
 #include "jni.h"
 #include "mirror/array.h"
-#include "mirror/art_method-inl.h"
 #include "mirror/class.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
diff --git a/test/454-get-vreg/get_vreg_jni.cc b/test/454-get-vreg/get_vreg_jni.cc
index 0ef2964..33bdc20 100644
--- a/test/454-get-vreg/get_vreg_jni.cc
+++ b/test/454-get-vreg/get_vreg_jni.cc
@@ -15,8 +15,8 @@
  */
 
 #include "arch/context.h"
+#include "art_method-inl.h"
 #include "jni.h"
-#include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 #include "stack.h"
 #include "thread.h"
@@ -34,7 +34,7 @@
         found_method_index_(0) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     std::string m_name(m->GetName());
 
     if (m_name.compare("testSimpleVReg") == 0) {
diff --git a/test/455-set-vreg/set_vreg_jni.cc b/test/455-set-vreg/set_vreg_jni.cc
index dffbfa4..7541189 100644
--- a/test/455-set-vreg/set_vreg_jni.cc
+++ b/test/455-set-vreg/set_vreg_jni.cc
@@ -15,8 +15,8 @@
  */
 
 #include "arch/context.h"
+#include "art_method-inl.h"
 #include "jni.h"
-#include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 #include "stack.h"
 #include "thread.h"
@@ -33,7 +33,7 @@
         this_value_(this_value) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     std::string m_name(m->GetName());
 
     if (m_name.compare("testIntVReg") == 0) {
diff --git a/test/457-regs/regs_jni.cc b/test/457-regs/regs_jni.cc
index 193ab9d..96f0e52 100644
--- a/test/457-regs/regs_jni.cc
+++ b/test/457-regs/regs_jni.cc
@@ -15,8 +15,8 @@
  */
 
 #include "arch/context.h"
+#include "art_method-inl.h"
 #include "jni.h"
-#include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 #include "stack.h"
 #include "thread.h"
@@ -32,7 +32,7 @@
       : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     std::string m_name(m->GetName());
 
     if (m_name.compare("mergeOk") == 0) {
diff --git a/test/461-get-reference-vreg/get_reference_vreg_jni.cc b/test/461-get-reference-vreg/get_reference_vreg_jni.cc
index a8ef684..23fe43d 100644
--- a/test/461-get-reference-vreg/get_reference_vreg_jni.cc
+++ b/test/461-get-reference-vreg/get_reference_vreg_jni.cc
@@ -15,8 +15,8 @@
  */
 
 #include "arch/context.h"
+#include "art_method-inl.h"
 #include "jni.h"
-#include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 #include "stack.h"
 #include "thread.h"
@@ -34,7 +34,7 @@
         found_method_index_(0) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     std::string m_name(m->GetName());
 
     if (m_name.compare("testThisWithInstanceCall") == 0) {
diff --git a/test/466-get-live-vreg/get_live_vreg_jni.cc b/test/466-get-live-vreg/get_live_vreg_jni.cc
index 4724e8e..c4f415b 100644
--- a/test/466-get-live-vreg/get_live_vreg_jni.cc
+++ b/test/466-get-live-vreg/get_live_vreg_jni.cc
@@ -15,8 +15,8 @@
  */
 
 #include "arch/context.h"
+#include "art_method-inl.h"
 #include "jni.h"
-#include "mirror/art_method-inl.h"
 #include "scoped_thread_state_change.h"
 #include "stack.h"
 #include "thread.h"
@@ -31,7 +31,7 @@
       : StackVisitor(thread, context, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     std::string m_name(m->GetName());
 
     if (m_name.compare("testLiveArgument") == 0) {