Merge "Enable jsr166 tests"
diff --git a/Android.mk b/Android.mk
index 3467f1d..54a33b2 100644
--- a/Android.mk
+++ b/Android.mk
@@ -119,6 +119,10 @@
 
 # Sync test files to the target, depends upon all things that must be pushed to the target.
 .PHONY: test-art-target-sync
+# Check if we need to sync. In case ART_TEST_ANDROID_ROOT is not empty,
+# the code below uses 'adb push' instead of 'adb sync', which does not
+# check if the files on the device have changed.
+ifneq ($(ART_TEST_NO_SYNC),true)
 ifeq ($(ART_TEST_ANDROID_ROOT),)
 test-art-target-sync: $(TEST_ART_TARGET_SYNC_DEPS)
 	adb root
@@ -130,9 +134,7 @@
 	adb wait-for-device push $(ANDROID_PRODUCT_OUT)/system $(ART_TEST_ANDROID_ROOT)
 	adb push $(ANDROID_PRODUCT_OUT)/data /data
 endif
-
-# Undefine variable now its served its purpose.
-TEST_ART_TARGET_SYNC_DEPS :=
+endif
 
 # "mm test-art" to build and run all tests on host and device
 .PHONY: test-art
@@ -377,6 +379,15 @@
 build-art-target: $(TARGET_OUT_EXECUTABLES)/art $(ART_TARGET_DEPENDENCIES) $(TARGET_CORE_IMG_OUTS)
 
 ########################################################################
+# Rules for building all dependencies for tests.
+
+.PHONY: build-art-host-tests
+build-art-host-tests:   build-art-host $(TEST_ART_RUN_TEST_DEPENDENCIES) $(ART_TEST_HOST_RUN_TEST_DEPENDENCIES) $(ART_TEST_HOST_GTEST_DEPENDENCIES)
+
+.PHONY: build-art-target-tests
+build-art-target-tests:   build-art-target $(TEST_ART_RUN_TEST_DEPENDENCIES) $(TEST_ART_TARGET_SYNC_DEPS)
+
+########################################################################
 # targets to switch back and forth from libdvm to libart
 
 .PHONY: use-art
@@ -467,3 +478,4 @@
 # Clear locally used variables.
 art_dont_bother :=
 art_test_bother :=
+TEST_ART_TARGET_SYNC_DEPS :=
diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk
index 3e427a3..b84154b 100644
--- a/build/Android.common_build.mk
+++ b/build/Android.common_build.mk
@@ -177,8 +177,8 @@
 ART_C_INCLUDES := \
   external/gtest/include \
   external/icu/icu4c/source/common \
-  external/valgrind/main/include \
-  external/valgrind/main \
+  external/valgrind/include \
+  external/valgrind \
   external/vixl/src \
   external/zlib \
 
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index bfc8956..5052187 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -105,12 +105,23 @@
   $(TARGET_CORE_IMAGE_default_no-pic_32) \
   imgdiagd
 
+# Oatdump test requires an image and oatfile to dump.
+ART_GTEST_oatdump_test_HOST_DEPS := \
+  $(HOST_CORE_IMAGE_default_no-pic_64) \
+  $(HOST_CORE_IMAGE_default_no-pic_32) \
+  $(HOST_OUT_EXECUTABLES)/oatdumpd
+ART_GTEST_oatdump_test_TARGET_DEPS := \
+  $(TARGET_CORE_IMAGE_default_no-pic_64) \
+  $(TARGET_CORE_IMAGE_default_no-pic_32) \
+  oatdump
+
 # The path for which all the source files are relative, not actually the current directory.
 LOCAL_PATH := art
 
 RUNTIME_GTEST_COMMON_SRC_FILES := \
   cmdline/cmdline_parser_test.cc \
   imgdiag/imgdiag_test.cc \
+  oatdump/oatdump_test.cc \
   runtime/arch/arch_test.cc \
   runtime/arch/instruction_set_test.cc \
   runtime/arch/instruction_set_features_test.cc \
@@ -124,6 +135,7 @@
   runtime/arch/x86_64/instruction_set_features_x86_64_test.cc \
   runtime/barrier_test.cc \
   runtime/base/bit_field_test.cc \
+  runtime/base/bit_utils_test.cc \
   runtime/base/bit_vector_test.cc \
   runtime/base/hash_set_test.cc \
   runtime/base/hex_dump_test.cc \
@@ -131,6 +143,7 @@
   runtime/base/mutex_test.cc \
   runtime/base/scoped_flock_test.cc \
   runtime/base/stringprintf_test.cc \
+  runtime/base/time_utils_test.cc \
   runtime/base/timing_logger_test.cc \
   runtime/base/variant_map_test.cc \
   runtime/base/unix_file/fd_file_test.cc \
@@ -300,6 +313,7 @@
 ART_TEST_TARGET_GTEST$(ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
 ART_TEST_TARGET_GTEST$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)_RULES :=
 ART_TEST_TARGET_GTEST_RULES :=
+ART_TEST_HOST_GTEST_DEPENDENCIES :=
 
 ART_GTEST_TARGET_ANDROID_ROOT := '/system'
 ifneq ($(ART_TEST_ANDROID_ROOT),)
@@ -361,11 +375,15 @@
   gtest_exe := $$(HOST_OUT_EXECUTABLES)/$(1)$$($(2)ART_PHONY_TEST_HOST_SUFFIX)
   # Dependencies for all host gtests.
   gtest_deps := $$(HOST_CORE_DEX_LOCATIONS) \
-    $$($(2)ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$$(ART_HOST_SHLIB_EXTENSION)
+    $$($(2)ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$$(ART_HOST_SHLIB_EXTENSION) \
+    $$(gtest_exe) \
+    $$(ART_GTEST_$(1)_HOST_DEPS) \
+    $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX))
 
+  ART_TEST_HOST_GTEST_DEPENDENCIES += $$(gtest_deps)
 
 .PHONY: $$(gtest_rule)
-$$(gtest_rule): $$(gtest_exe) $$(ART_GTEST_$(1)_HOST_DEPS) $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX)) $$(gtest_deps)
+$$(gtest_rule): $$(gtest_exe) $$(gtest_deps)
 	$(hide) ($$(call ART_TEST_SKIP,$$@) && $$< && $$(call ART_TEST_PASSED,$$@)) \
 	  || $$(call ART_TEST_FAILED,$$@)
 
@@ -375,7 +393,7 @@
 
 
 .PHONY: valgrind-$$(gtest_rule)
-valgrind-$$(gtest_rule): $$(gtest_exe) $$(ART_GTEST_$(1)_HOST_DEPS) $(foreach file,$(ART_GTEST_$(1)_DEX_DEPS),$(ART_TEST_HOST_GTEST_$(file)_DEX)) $$(gtest_deps) $(ART_VALGRIND_DEPENDENCIES)
+valgrind-$$(gtest_rule): $$(gtest_exe) $$(gtest_deps) $(ART_VALGRIND_DEPENDENCIES)
 	$(hide) $$(call ART_TEST_SKIP,$$@) && \
 	  VALGRIND_LIB=$(HOST_OUT)/lib64/valgrind \
 	  $(HOST_OUT_EXECUTABLES)/valgrind --leak-check=full --error-exitcode=1 $$< && \
diff --git a/cmdline/cmdline_parser.h b/cmdline/cmdline_parser.h
index e4af4f9..cebba65 100644
--- a/cmdline/cmdline_parser.h
+++ b/cmdline/cmdline_parser.h
@@ -30,7 +30,6 @@
 #include "cmdline_parse_result.h"
 
 #include "runtime/base/variant_map.h"
-#include "utils.h"
 
 #include <vector>
 #include <memory>
diff --git a/cmdline/cmdline_types.h b/cmdline/cmdline_types.h
index e02fe4b..28bd754 100644
--- a/cmdline/cmdline_types.h
+++ b/cmdline/cmdline_types.h
@@ -27,6 +27,7 @@
 #include "unit.h"
 #include "jdwp/jdwp.h"
 #include "runtime/base/logging.h"
+#include "runtime/base/time_utils.h"
 #include "gc/collector_type.h"
 #include "gc/space/large_object_space.h"
 #include "profiler_options.h"
diff --git a/cmdline/memory_representation.h b/cmdline/memory_representation.h
index 93387de..2619c31 100644
--- a/cmdline/memory_representation.h
+++ b/cmdline/memory_representation.h
@@ -20,24 +20,25 @@
 #include <string>
 #include <assert.h>
 #include <ostream>
-#include "utils.h"
+
+#include "base/bit_utils.h"
 
 namespace art {
 
 // An integral representation of bytes of memory.
 // The underlying runtime size_t value is guaranteed to be a multiple of Divisor.
-template <size_t Divisor = 1024>
+template <size_t kDivisor = 1024>
 struct Memory {
-  static_assert(IsPowerOfTwo(Divisor), "Divisor must be a power of 2");
+  static_assert(IsPowerOfTwo(kDivisor), "Divisor must be a power of 2");
 
-  static Memory<Divisor> FromBytes(size_t bytes) {
-    assert(bytes % Divisor == 0);
-    return Memory<Divisor>(bytes);
+  static Memory<kDivisor> FromBytes(size_t bytes) {
+    assert(bytes % kDivisor == 0);
+    return Memory<kDivisor>(bytes);
   }
 
   Memory() : Value(0u) {}
   Memory(size_t value) : Value(value) {  // NOLINT [runtime/explicit] [5]
-    assert(value % Divisor == 0);
+    assert(value % kDivisor == 0);
   }
   operator size_t() const { return Value; }
 
@@ -45,12 +46,10 @@
     return Value;
   }
 
-  static constexpr size_t kDivisor = Divisor;
-
   static const char* Name() {
     static std::string str;
     if (str.empty()) {
-      str = "Memory<" + std::to_string(Divisor) + '>';
+      str = "Memory<" + std::to_string(kDivisor) + '>';
     }
 
     return str.c_str();
@@ -59,9 +58,9 @@
   size_t Value;
 };
 
-template <size_t Divisor>
-std::ostream& operator<<(std::ostream& stream, Memory<Divisor> memory) {
-  return stream << memory.Value << '*' << Divisor;
+template <size_t kDivisor>
+std::ostream& operator<<(std::ostream& stream, Memory<kDivisor> memory) {
+  return stream << memory.Value << '*' << kDivisor;
 }
 
 using MemoryKiB = Memory<1024>;
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/compiled_method.h b/compiler/compiled_method.h
index 480d021..45a62bc 100644
--- a/compiler/compiled_method.h
+++ b/compiler/compiled_method.h
@@ -22,8 +22,8 @@
 #include <vector>
 
 #include "arch/instruction_set.h"
+#include "base/bit_utils.h"
 #include "method_reference.h"
-#include "utils.h"
 #include "utils/array_ref.h"
 #include "utils/swap_space.h"
 
diff --git a/compiler/compiler.cc b/compiler/compiler.cc
index 5e8ec1e..223affa 100644
--- a/compiler/compiler.cc
+++ b/compiler/compiler.cc
@@ -20,6 +20,7 @@
 #include "dex/quick/quick_compiler_factory.h"
 #include "driver/compiler_driver.h"
 #include "optimizing/optimizing_compiler.h"
+#include "utils.h"
 
 namespace art {
 
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/compiler_ir.cc b/compiler/dex/compiler_ir.cc
index 7fc1b03..6e1853b 100644
--- a/compiler/dex/compiler_ir.cc
+++ b/compiler/dex/compiler_ir.cc
@@ -22,6 +22,7 @@
 #include "dex/quick/mir_to_lir.h"
 #include "driver/compiler_driver.h"
 #include "mir_graph.h"
+#include "utils.h"
 
 namespace art {
 
diff --git a/compiler/dex/compiler_ir.h b/compiler/dex/compiler_ir.h
index dceea24..d28df1d 100644
--- a/compiler/dex/compiler_ir.h
+++ b/compiler/dex/compiler_ir.h
@@ -21,6 +21,7 @@
 #include <string>
 #include <vector>
 
+#include "arch/instruction_set.h"
 #include "base/arena_allocator.h"
 #include "base/scoped_arena_allocator.h"
 #include "base/timing_logger.h"
@@ -31,6 +32,7 @@
 
 class ClassLinker;
 class CompilerDriver;
+class DexFile;
 class Mir2Lir;
 class MIRGraph;
 
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/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc
index cc9dbe4..38f7d1e 100644
--- a/compiler/dex/local_value_numbering.cc
+++ b/compiler/dex/local_value_numbering.cc
@@ -16,9 +16,11 @@
 
 #include "local_value_numbering.h"
 
+#include "base/bit_utils.h"
 #include "global_value_numbering.h"
 #include "mir_field_info.h"
 #include "mir_graph.h"
+#include "utils.h"
 
 namespace art {
 
diff --git a/compiler/dex/local_value_numbering.h b/compiler/dex/local_value_numbering.h
index 67fb647..dff5e27 100644
--- a/compiler/dex/local_value_numbering.h
+++ b/compiler/dex/local_value_numbering.h
@@ -106,8 +106,7 @@
   }
 
   void SetOperandValueImpl(uint16_t s_reg, uint16_t value, SregValueMap* map) {
-    DCHECK_EQ(map->count(s_reg), 0u) << PrettyMethod(gvn_->cu_->method_idx, *gvn_->cu_->dex_file)
-        << " LVN id: " << id_ << ", s_reg: " << s_reg;
+    DCHECK_EQ(map->count(s_reg), 0u);
     map->Put(s_reg, value);
   }
 
diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc
index 9099e8a..1cff8dc 100644
--- a/compiler/dex/mir_analysis.cc
+++ b/compiler/dex/mir_analysis.cc
@@ -30,6 +30,7 @@
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
 #include "driver/dex_compilation_unit.h"
+#include "utils.h"
 
 namespace art {
 
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 1871f07..9fa5148 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -35,6 +35,7 @@
 #include "leb128.h"
 #include "pass_driver_me_post_opt.h"
 #include "stack.h"
+#include "utils.h"
 
 namespace art {
 
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 7385a8b..f038397 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 
 #include "base/arena_containers.h"
+#include "base/bit_utils.h"
 #include "base/scoped_arena_containers.h"
 #include "dex_file.h"
 #include "dex_instruction.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 217dbee..7b1ec39 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -31,6 +31,7 @@
 #include "quick/dex_file_to_method_inliner_map.h"
 #include "stack.h"
 #include "type_inference.h"
+#include "utils.h"
 
 namespace art {
 
@@ -248,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() {
@@ -315,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 2b2d6af..981ab2c 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -19,6 +19,8 @@
 #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"
 #include "dex/quick/dex_file_to_method_inliner_map.h"
@@ -26,10 +28,8 @@
 #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.h"
 #include "utils/dex_cache_arrays_layout-inl.h"
 
 namespace art {
@@ -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 7598e50..6d30e72 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -20,6 +20,7 @@
 
 #include "arch/instruction_set_features.h"
 #include "arm_lir.h"
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "dex/compiler_ir.h"
 #include "dex/mir_graph.h"
@@ -28,7 +29,6 @@
 #include "driver/compiler_driver.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "mirror/array-inl.h"
-#include "utils.h"
 
 namespace art {
 
@@ -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 5bf77aa..2253d10 100644
--- a/compiler/dex/quick/arm64/arm64_lir.h
+++ b/compiler/dex/quick/arm64/arm64_lir.h
@@ -35,14 +35,15 @@
  * r16-r17: Also known as ip0-ip1, respectively. Used as scratch registers by
  *          the linker, by the trampolines and other stubs (the backend uses
  *          these as temporary registers).
- * r18    : (rxSELF) is reserved (pointer to thread-local storage).
- * r19-r29: Callee save registers (promotion targets).
+ * r18    : Caller save register (used as temporary register).
+ * r19    : (rxSELF) is reserved (pointer to thread-local storage).
+ * r20-r29: Callee save registers (promotion targets).
  * r30    : (lr) is reserved (the link register).
  * rsp    : (sp) is reserved (the stack pointer).
  * rzr    : (zr) is reserved (the zero register).
  *
- * 18 core temps that codegen can use (r0-r17).
- * 10 core registers that can be used for promotion.
+ * 19 core temps that codegen can use (r0-r18).
+ * 9 core registers that can be used for promotion.
  *
  * Floating-point registers
  * v0-v31
@@ -71,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}
  * +--------------------------------------------+
@@ -90,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
  * +============================================+
  */
 
@@ -145,7 +146,7 @@
   // Aliases which are not defined in "ARM Architecture Reference, register names".
   rxIP0 = rx16,
   rxIP1 = rx17,
-  rxSELF = rx18,
+  rxSELF = rx19,
   rxLR = rx30,
   /*
    * FIXME: It's a bit awkward to define both 32 and 64-bit views of these - we'll only ever use
@@ -154,7 +155,7 @@
    */
   rwIP0 = rw16,
   rwIP1 = rw17,
-  rwSELF = rw18,
+  rwSELF = rw19,
   rwLR = rw30,
 };
 
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/fp_arm64.cc b/compiler/dex/quick/arm64/fp_arm64.cc
index 49b15fe..3b88021 100644
--- a/compiler/dex/quick/arm64/fp_arm64.cc
+++ b/compiler/dex/quick/arm64/fp_arm64.cc
@@ -20,7 +20,6 @@
 #include "base/logging.h"
 #include "dex/mir_graph.h"
 #include "dex/quick/mir_to_lir-inl.h"
-#include "utils.h"
 
 namespace art {
 
diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc
index 9340d01..31cf667 100644
--- a/compiler/dex/quick/arm64/int_arm64.cc
+++ b/compiler/dex/quick/arm64/int_arm64.cc
@@ -20,6 +20,7 @@
 
 #include "arch/instruction_set_features.h"
 #include "arm64_lir.h"
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "dex/compiler_ir.h"
 #include "dex/mir_graph.h"
@@ -28,7 +29,6 @@
 #include "driver/compiler_driver.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "mirror/array-inl.h"
-#include "utils.h"
 
 namespace art {
 
@@ -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 fc32ecd..6efa11e 100644
--- a/compiler/dex/quick/arm64/target_arm64.cc
+++ b/compiler/dex/quick/arm64/target_arm64.cc
@@ -51,19 +51,17 @@
      rs_d8, rs_d9, rs_d10, rs_d11, rs_d12, rs_d13, rs_d14, rs_d15,
      rs_d16, rs_d17, rs_d18, rs_d19, rs_d20, rs_d21, rs_d22, rs_d23,
      rs_d24, rs_d25, rs_d26, rs_d27, rs_d28, rs_d29, rs_d30, rs_d31};
-// Note: we are not able to call to C function since rs_xSELF is a special register need to be
-// preserved but would be scratched by native functions follow aapcs64.
 static constexpr RegStorage reserved_regs_arr[] = {rs_wSELF, rs_wsp, rs_wLR, rs_wzr};
 static constexpr RegStorage reserved64_regs_arr[] = {rs_xSELF, rs_sp, rs_xLR, rs_xzr};
 
 static constexpr RegStorage core_temps_arr[] =
     {rs_w0, rs_w1, rs_w2, rs_w3, rs_w4, rs_w5, rs_w6, rs_w7,
      rs_w8, rs_w9, rs_w10, rs_w11, rs_w12, rs_w13, rs_w14, rs_w15, rs_w16,
-     rs_w17};
+     rs_w17, rs_w18};
 static constexpr RegStorage core64_temps_arr[] =
     {rs_x0, rs_x1, rs_x2, rs_x3, rs_x4, rs_x5, rs_x6, rs_x7,
      rs_x8, rs_x9, rs_x10, rs_x11, rs_x12, rs_x13, rs_x14, rs_x15, rs_x16,
-     rs_x17};
+     rs_x17, rs_x18};
 static constexpr RegStorage sp_temps_arr[] =
     {rs_f0, rs_f1, rs_f2, rs_f3, rs_f4, rs_f5, rs_f6, rs_f7,
      rs_f16, rs_f17, rs_f18, rs_f19, rs_f20, rs_f21, rs_f22, rs_f23,
@@ -691,6 +689,7 @@
   Clobber(rs_x15);
   Clobber(rs_x16);
   Clobber(rs_x17);
+  Clobber(rs_x18);
   Clobber(rs_x30);
 
   Clobber(rs_f0);
@@ -859,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]);
@@ -895,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:
@@ -904,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 86bb69d..c803e65 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -670,7 +670,7 @@
 
 
 void Mir2Lir::CreateMappingTables() {
-  bool generate_src_map = cu_->compiler_driver->GetCompilerOptions().GetIncludeDebugSymbols();
+  bool generate_src_map = cu_->compiler_driver->GetCompilerOptions().GetGenerateDebugInfo();
 
   uint32_t pc2dex_data_size = 0u;
   uint32_t pc2dex_entries = 0u;
@@ -1071,7 +1071,7 @@
       pc_rel_temp_(nullptr),
       dex_cache_arrays_min_offset_(std::numeric_limits<uint32_t>::max()),
       cfi_(&last_lir_insn_,
-           cu->compiler_driver->GetCompilerOptions().GetIncludeCFI(),
+           cu->compiler_driver->GetCompilerOptions().GetGenerateDebugInfo(),
            arena),
       in_to_reg_storage_mapping_(arena) {
   switch_tables_.reserve(4);
@@ -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 0592c74..af10817 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -19,6 +19,7 @@
 #include <functional>
 
 #include "arch/arm/instruction_set_features_arm.h"
+#include "base/bit_utils.h"
 #include "base/macros.h"
 #include "dex/compiler_ir.h"
 #include "dex/mir_graph.h"
@@ -30,7 +31,6 @@
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_reference.h"
-#include "utils.h"
 #include "utils/dex_cache_arrays_layout-inl.h"
 #include "verifier/method_verifier.h"
 
@@ -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-inl.h b/compiler/dex/quick/mir_to_lir-inl.h
index 280dbbe..767fe25 100644
--- a/compiler/dex/quick/mir_to_lir-inl.h
+++ b/compiler/dex/quick/mir_to_lir-inl.h
@@ -21,6 +21,7 @@
 
 #include "base/logging.h"
 #include "dex/compiler_ir.h"
+#include "utils.h"
 
 namespace art {
 
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 4fdc728..73787e9 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -31,6 +31,7 @@
 #include "invoke_type.h"
 #include "lazy_debug_frame_opcode_writer.h"
 #include "leb128.h"
+#include "primitive.h"
 #include "safe_map.h"
 #include "utils/array_ref.h"
 #include "utils/dex_cache_arrays_layout.h"
@@ -981,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.
@@ -1007,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.
@@ -1116,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 b3c7355..dd68dd4 100644
--- a/compiler/dex/quick/quick_cfi_test.cc
+++ b/compiler/dex/quick/quick_cfi_test.cc
@@ -59,8 +59,7 @@
       false,
       CompilerOptions::kDefaultTopKProfileThreshold,
       false,
-      true,  // include_debug_symbols.
-      true,  // include_cfi
+      true,  // generate_debug_info.
       false,
       false,
       false,
@@ -100,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 48109d2..3032697 100644
--- a/compiler/dex/quick/quick_cfi_test_expected.inc
+++ b/compiler/dex/quick/quick_cfi_test_expected.inc
@@ -33,15 +33,15 @@
 // 0x00000014: .cfi_def_cfa_offset: 64
 
 static constexpr uint8_t expected_asm_kArm64[] = {
-    0xFF, 0x03, 0x01, 0xD1, 0xE8, 0xA7, 0x01, 0x6D, 0xF3, 0xD3, 0x02, 0xA9,
-    0xFE, 0x1F, 0x00, 0xF9, 0xE0, 0x03, 0x00, 0xB9, 0xE8, 0xA7, 0x41, 0x6D,
-    0xF3, 0xD3, 0x42, 0xA9, 0xFE, 0x1F, 0x40, 0xF9, 0xFF, 0x03, 0x01, 0x91,
+    0xFF, 0x03, 0x01, 0xD1, 0xE8, 0xA7, 0x01, 0x6D, 0xF4, 0xD7, 0x02, 0xA9,
+    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,
 };
 static constexpr uint8_t expected_cfi_kArm64[] = {
-    0x44, 0x0E, 0x40, 0x44, 0x05, 0x48, 0x0A, 0x05, 0x49, 0x08, 0x44, 0x93,
-    0x06, 0x94, 0x04, 0x44, 0x9E, 0x02, 0x44, 0x0A, 0x44, 0x06, 0x48, 0x06,
-    0x49, 0x44, 0xD3, 0xD4, 0x44, 0xDE, 0x44, 0x0E, 0x00, 0x44, 0x0B, 0x0E,
+    0x44, 0x0E, 0x40, 0x44, 0x05, 0x48, 0x0A, 0x05, 0x49, 0x08, 0x44, 0x94,
+    0x06, 0x95, 0x04, 0x44, 0x9E, 0x02, 0x44, 0x0A, 0x44, 0x06, 0x48, 0x06,
+    0x49, 0x44, 0xD4, 0xD5, 0x44, 0xDE, 0x44, 0x0E, 0x00, 0x44, 0x0B, 0x0E,
     0x40,
 };
 // 0x00000000: sub sp, sp, #0x40 (64)
@@ -49,19 +49,19 @@
 // 0x00000004: stp d8, d9, [sp, #24]
 // 0x00000008: .cfi_offset_extended: r72 at cfa-40
 // 0x00000008: .cfi_offset_extended: r73 at cfa-32
-// 0x00000008: stp x19, x20, [sp, #40]
-// 0x0000000c: .cfi_offset: r19 at cfa-24
-// 0x0000000c: .cfi_offset: r20 at cfa-16
+// 0x00000008: stp x20, x21, [sp, #40]
+// 0x0000000c: .cfi_offset: r20 at cfa-24
+// 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
 // 0x00000018: .cfi_restore_extended: r73
-// 0x00000018: ldp x19, x20, [sp, #40]
-// 0x0000001c: .cfi_restore: r19
+// 0x00000018: ldp x20, x21, [sp, #40]
 // 0x0000001c: .cfi_restore: r20
+// 0x0000001c: .cfi_restore: r21
 // 0x0000001c: ldr lr, [sp, #56]
 // 0x00000020: .cfi_restore: r30
 // 0x00000020: add sp, sp, #0x40 (64)
@@ -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/resource_mask.cc b/compiler/dex/quick/resource_mask.cc
index 57e8af3..817a69a 100644
--- a/compiler/dex/quick/resource_mask.cc
+++ b/compiler/dex/quick/resource_mask.cc
@@ -18,9 +18,9 @@
 
 #include "resource_mask.h"
 
+#include "base/bit_utils.h"
 #include "base/arena_allocator.h"
 #include "base/logging.h"
-#include "utils.h"
 
 namespace art {
 
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc
index 8467b71..12523ac 100644
--- a/compiler/dex/quick/x86/assemble_x86.cc
+++ b/compiler/dex/quick/x86/assemble_x86.cc
@@ -16,10 +16,12 @@
 
 #include "codegen_x86.h"
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "dex/compiler_ir.h"
 #include "dex/quick/mir_to_lir.h"
 #include "oat.h"
+#include "utils.h"
 #include "x86_lir.h"
 
 namespace art {
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 943bfc0..d993d93 100755
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -18,12 +18,12 @@
 
 #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 "utils.h"
 #include "x86_lir.h"
 
 namespace art {
@@ -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/quick_assemble_x86_test.cc b/compiler/dex/quick/x86/quick_assemble_x86_test.cc
index f58f206..798e23f 100644
--- a/compiler/dex/quick/x86/quick_assemble_x86_test.cc
+++ b/compiler/dex/quick/x86/quick_assemble_x86_test.cc
@@ -42,8 +42,7 @@
         false,
         CompilerOptions::kDefaultTopKProfileThreshold,
         false,
-        false,
-        false,
+        CompilerOptions::kDefaultGenerateDebugInfo,
         false,
         false,
         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 19d591b..a0dfcbe 100644
--- a/compiler/dex/type_inference.cc
+++ b/compiler/dex/type_inference.cc
@@ -25,6 +25,7 @@
 #include "mir_field_info.h"
 #include "mir_graph.h"
 #include "mir_method_info.h"
+#include "utils.h"
 
 namespace art {
 
@@ -685,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 c9b29bf..adc3b54 100644
--- a/compiler/dex/type_inference.h
+++ b/compiler/dex/type_inference.h
@@ -17,6 +17,7 @@
 #ifndef ART_COMPILER_DEX_TYPE_INFERENCE_H_
 #define ART_COMPILER_DEX_TYPE_INFERENCE_H_
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "base/arena_object.h"
 #include "base/scoped_arena_containers.h"
@@ -80,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 7cb7489..22fcf87 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -28,7 +28,9 @@
 #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"
 #include "class_linker-inl.h"
 #include "compiled_class.h"
@@ -49,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"
@@ -541,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;
@@ -585,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();
@@ -687,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) {
@@ -727,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;
 }
@@ -825,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 =
@@ -838,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);
@@ -854,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;
     }
@@ -902,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);
 
@@ -921,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);
       }
     }
@@ -949,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);
     }
   }
@@ -959,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_;
@@ -1241,7 +1242,7 @@
   mirror::Class* referrer_class;
   mirror::DexCache* dex_cache;
   {
-    StackHandleScope<3> hs(soa.Self());
+    StackHandleScope<2> hs(soa.Self());
     Handle<mirror::DexCache> dex_cache_handle(
         hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())));
     Handle<mirror::ClassLoader> class_loader_handle(
@@ -1333,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,
@@ -1346,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.
@@ -1374,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;
     }
@@ -1388,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.
@@ -1402,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 {
@@ -1430,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
@@ -1468,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);
@@ -1491,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) {
@@ -1505,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;
       }
     }
@@ -1772,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 2b0985a..68c905e 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -24,6 +24,7 @@
 
 #include "arch/instruction_set.h"
 #include "base/arena_allocator.h"
+#include "base/bit_utils.h"
 #include "base/mutex.h"
 #include "base/timing_logger.h"
 #include "class_reference.h"
@@ -41,7 +42,6 @@
 #include "utils/dedupe_set.h"
 #include "utils/dex_cache_arrays_layout.h"
 #include "utils/swap_space.h"
-#include "utils.h"
 
 namespace art {
 
@@ -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/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index c5fc98a..226e6b7 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -30,8 +30,7 @@
       include_patch_information_(kDefaultIncludePatchInformation),
       top_k_profile_threshold_(kDefaultTopKProfileThreshold),
       debuggable_(false),
-      include_debug_symbols_(kDefaultIncludeDebugSymbols),
-      include_cfi_(false),
+      generate_debug_info_(kDefaultGenerateDebugInfo),
       implicit_null_checks_(true),
       implicit_so_checks_(true),
       implicit_suspend_checks_(false),
@@ -56,8 +55,7 @@
                                  bool include_patch_information,
                                  double top_k_profile_threshold,
                                  bool debuggable,
-                                 bool include_debug_symbols,
-                                 bool include_cfi,
+                                 bool generate_debug_info,
                                  bool implicit_null_checks,
                                  bool implicit_so_checks,
                                  bool implicit_suspend_checks,
@@ -76,8 +74,7 @@
     include_patch_information_(include_patch_information),
     top_k_profile_threshold_(top_k_profile_threshold),
     debuggable_(debuggable),
-    include_debug_symbols_(include_debug_symbols),
-    include_cfi_(include_cfi),
+    generate_debug_info_(generate_debug_info),
     implicit_null_checks_(implicit_null_checks),
     implicit_so_checks_(implicit_so_checks),
     implicit_suspend_checks_(implicit_suspend_checks),
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index bf3f8ec..356663b 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -49,7 +49,7 @@
   static const size_t kDefaultTinyMethodThreshold = 20;
   static const size_t kDefaultNumDexMethodsThreshold = 900;
   static constexpr double kDefaultTopKProfileThreshold = 90.0;
-  static const bool kDefaultIncludeDebugSymbols = kIsDebugBuild;
+  static const bool kDefaultGenerateDebugInfo = kIsDebugBuild;
   static const bool kDefaultIncludePatchInformation = false;
 
   CompilerOptions();
@@ -64,8 +64,7 @@
                   bool include_patch_information,
                   double top_k_profile_threshold,
                   bool debuggable,
-                  bool include_debug_symbols,
-                  bool include_cfi,
+                  bool generate_debug_info,
                   bool implicit_null_checks,
                   bool implicit_so_checks,
                   bool implicit_suspend_checks,
@@ -146,13 +145,8 @@
     return debuggable_;
   }
 
-  bool GetIncludeDebugSymbols() const {
-    return include_debug_symbols_;
-  }
-
-  bool GetIncludeCFI() const {
-    // include-debug-symbols implies include-cfi.
-    return include_cfi_ || include_debug_symbols_;
+  bool GetGenerateDebugInfo() const {
+    return generate_debug_info_;
   }
 
   bool GetImplicitNullChecks() const {
@@ -212,8 +206,7 @@
   // When using a profile file only the top K% of the profiled samples will be compiled.
   const double top_k_profile_threshold_;
   const bool debuggable_;
-  const bool include_debug_symbols_;
-  const bool include_cfi_;
+  const bool generate_debug_info_;
   const bool implicit_null_checks_;
   const bool implicit_so_checks_;
   const bool implicit_suspend_checks_;
diff --git a/compiler/dwarf/debug_frame_opcode_writer.h b/compiler/dwarf/debug_frame_opcode_writer.h
index 4112c84..d8077d5 100644
--- a/compiler/dwarf/debug_frame_opcode_writer.h
+++ b/compiler/dwarf/debug_frame_opcode_writer.h
@@ -17,10 +17,10 @@
 #ifndef ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_
 #define ART_COMPILER_DWARF_DEBUG_FRAME_OPCODE_WRITER_H_
 
+#include "base/bit_utils.h"
 #include "dwarf/dwarf_constants.h"
 #include "dwarf/register.h"
 #include "dwarf/writer.h"
-#include "utils.h"
 
 namespace art {
 namespace dwarf {
diff --git a/compiler/dwarf/dwarf_test.h b/compiler/dwarf/dwarf_test.h
index 3afb5ea..f819c49 100644
--- a/compiler/dwarf/dwarf_test.h
+++ b/compiler/dwarf/dwarf_test.h
@@ -25,7 +25,6 @@
 #include <string>
 #include <sys/types.h>
 
-#include "utils.h"
 #include "base/unix_file/fd_file.h"
 #include "common_runtime_test.h"
 #include "elf_builder.h"
diff --git a/compiler/dwarf/writer.h b/compiler/dwarf/writer.h
index 3b9c558..e703aee 100644
--- a/compiler/dwarf/writer.h
+++ b/compiler/dwarf/writer.h
@@ -18,9 +18,9 @@
 #define ART_COMPILER_DWARF_WRITER_H_
 
 #include <vector>
-#include "leb128.h"
+#include "base/bit_utils.h"
 #include "base/logging.h"
-#include "utils.h"
+#include "leb128.h"
 
 namespace art {
 namespace dwarf {
diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h
index 972bd08..bbd962f 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -20,6 +20,7 @@
 #include <vector>
 
 #include "arch/instruction_set.h"
+#include "base/bit_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "buffered_output_stream.h"
 #include "elf_utils.h"
@@ -56,12 +57,12 @@
    public:
     Section(const std::string& name, Elf_Word type, Elf_Word flags,
             const Section* link, Elf_Word info, Elf_Word align, Elf_Word entsize)
-        : header_(new Elf_Shdr()), section_index_(0), name_(name), link_(link) {
-      header_->sh_type = type;
-      header_->sh_flags = flags;
-      header_->sh_info = info;
-      header_->sh_addralign = align;
-      header_->sh_entsize = entsize;
+        : header_(), section_index_(0), name_(name), link_(link) {
+      header_.sh_type = type;
+      header_.sh_flags = flags;
+      header_.sh_info = info;
+      header_.sh_addralign = align;
+      header_.sh_entsize = entsize;
     }
     virtual ~Section() {}
 
@@ -79,11 +80,11 @@
     }
 
     const Elf_Shdr* GetHeader() const {
-      return header_.get();
+      return &header_;
     }
 
     Elf_Shdr* GetHeader() {
-      return header_.get();
+      return &header_;
     }
 
     Elf_Word GetSectionIndex() const {
@@ -100,9 +101,7 @@
     }
 
    private:
-    // Elf_Shdr is somewhat large so allocate it on the heap.
-    // Otherwise we get in trouble with stack frame sizes.
-    std::unique_ptr<Elf_Shdr> header_;
+    Elf_Shdr header_;
     Elf_Word section_index_;
     const std::string name_;
     const Section* const link_;
@@ -167,6 +166,10 @@
           patched_(false), patch_(patch), patch_base_section_(patch_base_section) {
     }
 
+    RawSection(const std::string& name, Elf_Word type)
+        : RawSection(name, type, 0, nullptr, 0, 1, 0, nullptr, nullptr) {
+    }
+
     Elf_Word GetSize() const OVERRIDE {
       return buffer_.size();
     }
@@ -264,7 +267,7 @@
   class StrtabSection FINAL : public Section {
    public:
     StrtabSection(const std::string& name, Elf_Word flags)
-        : Section(name, SHT_STRTAB, flags, nullptr, 0, 1, 1) {
+        : Section(name, SHT_STRTAB, flags, nullptr, 0, 1, 0) {
       buffer_.reserve(4 * KB);
       // The first entry of strtab must be empty string.
       buffer_ += '\0';
@@ -307,7 +310,7 @@
 
     SymtabSection(const std::string& name, Elf_Word type, Elf_Word flags,
                   StrtabSection* strtab)
-        : Section(name, type, flags, strtab, 0, sizeof(Elf_Word), sizeof(Elf_Sym)),
+        : Section(name, type, flags, strtab, 0, sizeof(Elf_Off), sizeof(Elf_Sym)),
           strtab_(strtab) {
     }
 
@@ -500,7 +503,7 @@
       text_(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR,
             nullptr, 0, kPageSize, 0, text_size, text_writer),
       bss_(".bss", bss_size),
-      dynamic_(".dynamic", &dynsym_),
+      dynamic_(".dynamic", &dynstr_),
       strtab_(".strtab", 0),
       symtab_(".symtab", SHT_SYMTAB, 0, &strtab_),
       shstrtab_(".shstrtab", 0) {
@@ -642,11 +645,10 @@
     // It is easiest to just reserve a fixed amount of space for them.
     constexpr size_t kMaxProgramHeaders = 8;
     constexpr size_t kProgramHeadersOffset = sizeof(Elf_Ehdr);
-    constexpr size_t kProgramHeadersSize = sizeof(Elf_Phdr) * kMaxProgramHeaders;
 
     // Layout of all sections - determine the final file offsets and addresses.
     // This must be done after we have built all sections and know their size.
-    Elf_Off file_offset = kProgramHeadersOffset + kProgramHeadersSize;
+    Elf_Off file_offset = kProgramHeadersOffset + sizeof(Elf_Phdr) * kMaxProgramHeaders;
     Elf_Addr load_address = file_offset;
     std::vector<Elf_Shdr> section_headers;
     section_headers.reserve(1u + sections.size());
@@ -675,7 +677,7 @@
       // Collect section headers into continuous array for convenience.
       section_headers.push_back(*header);
     }
-    Elf_Off section_headers_offset = RoundUp(file_offset, sizeof(Elf_Word));
+    Elf_Off section_headers_offset = RoundUp(file_offset, sizeof(Elf_Off));
 
     // Create program headers now that we know the layout of the whole file.
     // Each segment contains one or more sections which are mapped together.
@@ -683,8 +685,7 @@
     // PT_LOAD does the mapping.  Other PT_* types allow the program to locate
     // interesting parts of memory and their addresses overlap with PT_LOAD.
     std::vector<Elf_Phdr> program_headers;
-    program_headers.push_back(MakeProgramHeader(PT_PHDR, PF_R,
-      kProgramHeadersOffset, kProgramHeadersSize, sizeof(Elf_Word)));
+    program_headers.push_back(Elf_Phdr());  // Placeholder for PT_PHDR.
     // Create the main LOAD R segment which spans all sections up to .rodata.
     const Elf_Shdr* rodata = rodata_.GetHeader();
     program_headers.push_back(MakeProgramHeader(PT_LOAD, PF_R,
@@ -710,6 +711,9 @@
         program_headers.push_back(MakeProgramHeader(PT_GNU_EH_FRAME, PF_R, *eh_frame_hdr));
       }
     }
+    DCHECK_EQ(program_headers[0].p_type, 0u);  // Check placeholder.
+    program_headers[0] = MakeProgramHeader(PT_PHDR, PF_R,
+      kProgramHeadersOffset, program_headers.size() * sizeof(Elf_Phdr), sizeof(Elf_Off));
     CHECK_LE(program_headers.size(), kMaxProgramHeaders);
 
     // Create the main ELF header.
@@ -778,10 +782,12 @@
 
   template<typename T>
   static bool WriteArray(File* elf_file, const T* data, size_t count) {
-    DCHECK(data != nullptr);
-    if (!elf_file->WriteFully(data, count * sizeof(T))) {
-      PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
-      return false;
+    if (count != 0) {
+      DCHECK(data != nullptr);
+      if (!elf_file->WriteFully(data, count * sizeof(T))) {
+        PLOG(ERROR) << "Failed to write to file " << elf_file->GetPath();
+        return false;
+      }
     }
     return true;
   }
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/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index a1aabc3..c68bbc0 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -25,6 +25,7 @@
 #include "dwarf/headers.h"
 #include "dwarf/register.h"
 #include "oat_writer.h"
+#include "utils.h"
 
 namespace art {
 namespace dwarf {
@@ -243,6 +244,7 @@
                         std::vector<uintptr_t>* debug_line_patches) {
   const std::vector<OatWriter::DebugInfo>& method_infos = oat_writer->GetMethodDebugInfo();
   const InstructionSet isa = compiler->GetInstructionSet();
+  const bool is64bit = Is64BitInstructionSet(isa);
 
   // Find all addresses (low_pc) which contain deduped methods.
   // The first instance of method is not marked deduped_, but the rest is.
@@ -280,7 +282,7 @@
     }
 
     size_t debug_abbrev_offset = debug_abbrev->size();
-    DebugInfoEntryWriter<> info(false /* 32 bit */, debug_abbrev);
+    DebugInfoEntryWriter<> info(is64bit, debug_abbrev);
     info.StartTag(DW_TAG_compile_unit, DW_CHILDREN_yes);
     info.WriteStrp(DW_AT_producer, "Android dex2oat", debug_str);
     info.WriteData1(DW_AT_language, DW_LANG_Java);
@@ -325,7 +327,7 @@
       case kX86_64:
         break;
     }
-    DebugLineOpCodeWriter<> opcodes(false /* 32bit */, code_factor_bits_);
+    DebugLineOpCodeWriter<> opcodes(is64bit, code_factor_bits_);
     opcodes.SetAddress(cunit_low_pc);
     if (dwarf_isa != -1) {
       opcodes.SetISA(dwarf_isa);
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 96dd7ca..dce1e86 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -19,6 +19,7 @@
 #include <unordered_map>
 #include <unordered_set>
 
+#include "base/casts.h"
 #include "base/logging.h"
 #include "base/unix_file/fd_file.h"
 #include "compiled_method.h"
@@ -43,7 +44,17 @@
 // it is used by C++ exception handling (which we do not use so we
 // can choose either).  C++ compilers generally tend to use .eh_frame
 // because if they need it sometimes, they might as well always use it.
-constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_EH_FRAME_FORMAT;
+// Let's use .debug_frame because it is easier to strip or compress.
+constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
+
+// The ARM specification defines three special mapping symbols
+// $a, $t and $d which mark ARM, Thumb and data ranges respectively.
+// These symbols can be used by tools, for example, to pretty
+// print instructions correctly.  Objdump will use them if they
+// exist, but it will still work well without them.
+// However, these extra symbols take space, so let's just generate
+// one symbol which marks the whole .text section as code.
+constexpr bool kGenerateSingleArmMappingSymbol = true;
 
 template <typename ElfTypes>
 bool ElfWriterQuick<ElfTypes>::Create(File* elf_file,
@@ -59,36 +70,17 @@
 template <typename ElfTypes>
 static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer);
 
-// Encode patch locations in .oat_patches format.
+// Encode patch locations as LEB128 list of deltas between consecutive addresses.
 template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::EncodeOatPatches(
-    const OatWriter::PatchLocationsMap& sections,
-    std::vector<uint8_t>* buffer) {
-  for (const auto& section : sections) {
-    const std::string& name = section.first;
-    std::vector<uintptr_t>* locations = section.second.get();
-    DCHECK(!name.empty());
-    std::sort(locations->begin(), locations->end());
-    // Reserve buffer space - guess 2 bytes per ULEB128.
-    buffer->reserve(buffer->size() + name.size() + locations->size() * 2);
-    // Write null-terminated section name.
-    const uint8_t* name_data = reinterpret_cast<const uint8_t*>(name.c_str());
-    buffer->insert(buffer->end(), name_data, name_data + name.size() + 1);
-    // Write placeholder for data length.
-    size_t length_pos = buffer->size();
-    EncodeUnsignedLeb128(buffer, UINT32_MAX);
-    // Write LEB128 encoded list of advances (deltas between consequtive addresses).
-    size_t data_pos = buffer->size();
-    uintptr_t address = 0;  // relative to start of section.
-    for (uintptr_t location : *locations) {
-      DCHECK_LT(location - address, UINT32_MAX) << "Large gap between patch locations";
-      EncodeUnsignedLeb128(buffer, location - address);
-      address = location;
-    }
-    // Update length.
-    UpdateUnsignedLeb128(buffer->data() + length_pos, buffer->size() - data_pos);
+void ElfWriterQuick<ElfTypes>::EncodeOatPatches(const std::vector<uintptr_t>& locations,
+                                                std::vector<uint8_t>* buffer) {
+  buffer->reserve(buffer->size() + locations.size() * 2);  // guess 2 bytes per ULEB128.
+  uintptr_t address = 0;  // relative to start of section.
+  for (uintptr_t location : locations) {
+    DCHECK_GE(location, address) << "Patch locations are not in sorted order";
+    EncodeUnsignedLeb128(buffer, dchecked_integral_cast<uint32_t>(location - address));
+    address = location;
   }
-  buffer->push_back(0);  // End of sections.
 }
 
 class RodataWriter FINAL : public CodeOutput {
@@ -164,79 +156,95 @@
       isa, rodata_size, &rodata_writer, text_size, &text_writer, bss_size));
 
   // Add debug sections.
-  // They are stack allocated here (in the same scope as the builder),
-  // but they are registred with the builder only if they are used.
+  // They are allocated here (in the same scope as the builder),
+  // but they are registered with the builder only if they are used.
   using RawSection = typename ElfBuilder<ElfTypes>::RawSection;
   const auto* text = builder->GetText();
   const bool is64bit = Is64BitInstructionSet(isa);
   const int pointer_size = GetInstructionSetPointerSize(isa);
-  RawSection eh_frame(".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0,
-                      is64bit ? Patch<Elf_Addr, uint64_t, kPointerRelativeAddress> :
-                                Patch<Elf_Addr, uint32_t, kPointerRelativeAddress>,
-                      text);
-  RawSection eh_frame_hdr(".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0,
-                          Patch<Elf_Addr, uint32_t, kSectionRelativeAddress>, text);
-  RawSection debug_frame(".debug_frame", SHT_PROGBITS, 0, nullptr, 0, pointer_size, 0,
-                         is64bit ? Patch<Elf_Addr, uint64_t, kAbsoluteAddress> :
-                                   Patch<Elf_Addr, uint32_t, kAbsoluteAddress>,
-                         text);
-  RawSection debug_info(".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
-                        Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
-  RawSection debug_abbrev(".debug_abbrev", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
-  RawSection debug_str(".debug_str", SHT_PROGBITS, 0, nullptr, 0, 1, 0);
-  RawSection debug_line(".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
-                        Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text);
+  std::unique_ptr<RawSection> eh_frame(new RawSection(
+      ".eh_frame", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, kPageSize, 0,
+      is64bit ? Patch<Elf_Addr, uint64_t, kPointerRelativeAddress> :
+                Patch<Elf_Addr, uint32_t, kPointerRelativeAddress>,
+      text));
+  std::unique_ptr<RawSection> eh_frame_hdr(new RawSection(
+      ".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, nullptr, 0, 4, 0,
+      Patch<Elf_Addr, uint32_t, kSectionRelativeAddress>, text));
+  std::unique_ptr<RawSection> debug_frame(new RawSection(
+      ".debug_frame", SHT_PROGBITS, 0, nullptr, 0, pointer_size, 0,
+      is64bit ? Patch<Elf_Addr, uint64_t, kAbsoluteAddress> :
+                Patch<Elf_Addr, uint32_t, kAbsoluteAddress>,
+      text));
+  std::unique_ptr<RawSection> debug_frame_oat_patches(new RawSection(
+      ".debug_frame.oat_patches", SHT_OAT_PATCH));
+  std::unique_ptr<RawSection> debug_info(new RawSection(
+      ".debug_info", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
+      Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text));
+  std::unique_ptr<RawSection> debug_info_oat_patches(new RawSection(
+      ".debug_info.oat_patches", SHT_OAT_PATCH));
+  std::unique_ptr<RawSection> debug_abbrev(new RawSection(
+      ".debug_abbrev", SHT_PROGBITS));
+  std::unique_ptr<RawSection> debug_str(new RawSection(
+      ".debug_str", SHT_PROGBITS));
+  std::unique_ptr<RawSection> debug_line(new RawSection(
+      ".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0,
+      Patch<Elf_Addr, uint32_t, kAbsoluteAddress>, text));
+  std::unique_ptr<RawSection> debug_line_oat_patches(new RawSection(
+      ".debug_line.oat_patches", SHT_OAT_PATCH));
   if (!oat_writer->GetMethodDebugInfo().empty()) {
-    if (compiler_driver_->GetCompilerOptions().GetIncludeCFI()) {
+    if (compiler_driver_->GetCompilerOptions().GetGenerateDebugInfo()) {
+      // Generate CFI (stack unwinding information).
       if (kCFIFormat == dwarf::DW_EH_FRAME_FORMAT) {
         dwarf::WriteCFISection(
             compiler_driver_, oat_writer,
             dwarf::DW_EH_PE_pcrel, kCFIFormat,
-            eh_frame.GetBuffer(), eh_frame.GetPatchLocations(),
-            eh_frame_hdr.GetBuffer(), eh_frame_hdr.GetPatchLocations());
-        builder->RegisterSection(&eh_frame);
-        builder->RegisterSection(&eh_frame_hdr);
+            eh_frame->GetBuffer(), eh_frame->GetPatchLocations(),
+            eh_frame_hdr->GetBuffer(), eh_frame_hdr->GetPatchLocations());
+        builder->RegisterSection(eh_frame.get());
+        builder->RegisterSection(eh_frame_hdr.get());
       } else {
         DCHECK(kCFIFormat == dwarf::DW_DEBUG_FRAME_FORMAT);
         dwarf::WriteCFISection(
             compiler_driver_, oat_writer,
             dwarf::DW_EH_PE_absptr, kCFIFormat,
-            debug_frame.GetBuffer(), debug_frame.GetPatchLocations(),
+            debug_frame->GetBuffer(), debug_frame->GetPatchLocations(),
             nullptr, nullptr);
-        builder->RegisterSection(&debug_frame);
-        *oat_writer->GetAbsolutePatchLocationsFor(".debug_frame") =
-            *debug_frame.GetPatchLocations();
+        builder->RegisterSection(debug_frame.get());
+        EncodeOatPatches(*debug_frame->GetPatchLocations(),
+                         debug_frame_oat_patches->GetBuffer());
+        builder->RegisterSection(debug_frame_oat_patches.get());
       }
-    }
-    if (compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
       // Add methods to .symtab.
       WriteDebugSymbols(builder.get(), oat_writer);
       // Generate DWARF .debug_* sections.
       dwarf::WriteDebugSections(
           compiler_driver_, oat_writer,
-          debug_info.GetBuffer(), debug_info.GetPatchLocations(),
-          debug_abbrev.GetBuffer(),
-          debug_str.GetBuffer(),
-          debug_line.GetBuffer(), debug_line.GetPatchLocations());
-      builder->RegisterSection(&debug_info);
-      builder->RegisterSection(&debug_abbrev);
-      builder->RegisterSection(&debug_str);
-      builder->RegisterSection(&debug_line);
-      *oat_writer->GetAbsolutePatchLocationsFor(".debug_info") =
-          *debug_info.GetPatchLocations();
-      *oat_writer->GetAbsolutePatchLocationsFor(".debug_line") =
-          *debug_line.GetPatchLocations();
+          debug_info->GetBuffer(), debug_info->GetPatchLocations(),
+          debug_abbrev->GetBuffer(),
+          debug_str->GetBuffer(),
+          debug_line->GetBuffer(), debug_line->GetPatchLocations());
+      builder->RegisterSection(debug_info.get());
+      EncodeOatPatches(*debug_info->GetPatchLocations(),
+                       debug_info_oat_patches->GetBuffer());
+      builder->RegisterSection(debug_info_oat_patches.get());
+      builder->RegisterSection(debug_abbrev.get());
+      builder->RegisterSection(debug_str.get());
+      builder->RegisterSection(debug_line.get());
+      EncodeOatPatches(*debug_line->GetPatchLocations(),
+                       debug_line_oat_patches->GetBuffer());
+      builder->RegisterSection(debug_line_oat_patches.get());
     }
   }
 
-  // Add relocation section.
-  RawSection oat_patches(".oat_patches", SHT_OAT_PATCH, 0, nullptr, 0, 1, 0);
-  if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation() ||
-      // ElfWriter::Fixup will be called regardless and it needs to be able
-      // to patch debug sections so we have to include patches for them.
-      compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols()) {
-    EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(), oat_patches.GetBuffer());
-    builder->RegisterSection(&oat_patches);
+  // Add relocation section for .text.
+  std::unique_ptr<RawSection> text_oat_patches(new RawSection(
+      ".text.oat_patches", SHT_OAT_PATCH));
+  if (compiler_driver_->GetCompilerOptions().GetIncludePatchInformation()) {
+    // Note that ElfWriter::Fixup will be called regardless and therefore
+    // we need to include oat_patches for debug sections unconditionally.
+    EncodeOatPatches(oat_writer->GetAbsolutePatchLocations(),
+                     text_oat_patches->GetBuffer());
+    builder->RegisterSection(text_oat_patches.get());
   }
 
   return builder->Write(elf_file_);
@@ -245,6 +253,7 @@
 template <typename ElfTypes>
 static void WriteDebugSymbols(ElfBuilder<ElfTypes>* builder, OatWriter* oat_writer) {
   const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetMethodDebugInfo();
+  bool generated_mapping_symbol = false;
 
   // Find all addresses (low_pc) which contain deduped methods.
   // The first instance of method is not marked deduped_, but the rest is.
@@ -273,9 +282,14 @@
 
     // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
     // instructions, so that disassembler tools can correctly disassemble.
+    // Note that even if we generate just a single mapping symbol, ARM's Streamline
+    // requires it to match function symbol.  Just address 0 does not work.
     if (it->compiled_method_->GetInstructionSet() == kThumb2) {
-      symtab->AddSymbol("$t", builder->GetText(), it->low_pc_ & ~1, true,
-                        0, STB_LOCAL, STT_NOTYPE);
+      if (!generated_mapping_symbol || !kGenerateSingleArmMappingSymbol) {
+        symtab->AddSymbol("$t", builder->GetText(), it->low_pc_ & ~1, true,
+                          0, STB_LOCAL, STT_NOTYPE);
+        generated_mapping_symbol = true;
+      }
     }
   }
 }
diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h
index 955b568..fd202ee 100644
--- a/compiler/elf_writer_quick.h
+++ b/compiler/elf_writer_quick.h
@@ -35,7 +35,7 @@
                      const CompilerDriver& driver)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static void EncodeOatPatches(const OatWriter::PatchLocationsMap& sections,
+  static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
                                std::vector<uint8_t>* buffer);
 
  protected:
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index 08523d8..ccf34b8 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -88,73 +88,41 @@
   }
 }
 
-// Run only on host since we do unaligned memory accesses.
-#ifndef HAVE_ANDROID_OS
-
-static void PatchSection(const std::vector<uintptr_t>& patch_locations,
-                         std::vector<uint8_t>* section, int32_t delta) {
-  for (uintptr_t location : patch_locations) {
-    *reinterpret_cast<int32_t*>(section->data() + location) += delta;
-  }
-}
-
 TEST_F(ElfWriterTest, EncodeDecodeOatPatches) {
-  std::vector<uint8_t> oat_patches;  // Encoded patches.
+  const std::vector<std::vector<uintptr_t>> test_data {
+      { 0, 4, 8, 15, 128, 200 },
+      { 8, 8 + 127 },
+      { 8, 8 + 128 },
+      { },
+  };
+  for (const auto& patch_locations : test_data) {
+    constexpr int32_t delta = 0x11235813;
 
-  // Encode patch locations for a few sections.
-  OatWriter::PatchLocationsMap sections;
-  std::vector<uintptr_t> patches0 { 0, 4, 8, 15, 128, 200 };  // NOLINT
-  sections.emplace(".section0", std::unique_ptr<std::vector<uintptr_t>>(
-      new std::vector<uintptr_t> { patches0 }));
-  std::vector<uintptr_t> patches1 { 8, 127 };  // NOLINT
-  sections.emplace(".section1", std::unique_ptr<std::vector<uintptr_t>>(
-      new std::vector<uintptr_t> { patches1 }));
-  std::vector<uintptr_t> patches2 { };  // NOLINT
-  sections.emplace(".section2", std::unique_ptr<std::vector<uintptr_t>>(
-      new std::vector<uintptr_t> { patches2 }));
-  ElfWriterQuick32::EncodeOatPatches(sections, &oat_patches);
+    // Encode patch locations.
+    std::vector<uint8_t> oat_patches;
+    ElfWriterQuick32::EncodeOatPatches(patch_locations, &oat_patches);
 
-  // Create buffers to be patched.
-  std::vector<uint8_t> initial_data(256);
-  for (size_t i = 0; i < initial_data.size(); i++) {
-    initial_data[i] = i;
+    // Create buffer to be patched.
+    std::vector<uint8_t> initial_data(256);
+    for (size_t i = 0; i < initial_data.size(); i++) {
+      initial_data[i] = i;
+    }
+
+    // Patch manually.
+    std::vector<uint8_t> expected = initial_data;
+    for (uintptr_t location : patch_locations) {
+      typedef __attribute__((__aligned__(1))) uint32_t UnalignedAddress;
+      *reinterpret_cast<UnalignedAddress*>(expected.data() + location) += delta;
+    }
+
+    // Decode and apply patch locations.
+    std::vector<uint8_t> actual = initial_data;
+    ElfFileImpl32::ApplyOatPatches(
+        oat_patches.data(), oat_patches.data() + oat_patches.size(), delta,
+        actual.data(), actual.data() + actual.size());
+
+    EXPECT_EQ(expected, actual);
   }
-  std::vector<uint8_t> section0_expected = initial_data;
-  std::vector<uint8_t> section1_expected = initial_data;
-  std::vector<uint8_t> section2_expected = initial_data;
-  std::vector<uint8_t> section0_actual = initial_data;
-  std::vector<uint8_t> section1_actual = initial_data;
-  std::vector<uint8_t> section2_actual = initial_data;
-
-  // Patch manually.
-  constexpr int32_t delta = 0x11235813;
-  PatchSection(patches0, &section0_expected, delta);
-  PatchSection(patches1, &section1_expected, delta);
-  PatchSection(patches2, &section2_expected, delta);
-
-  // Decode and apply patch locations.
-  bool section0_successful = ElfFileImpl32::ApplyOatPatches(
-      oat_patches.data(), oat_patches.data() + oat_patches.size(),
-      ".section0", delta,
-      section0_actual.data(), section0_actual.data() + section0_actual.size());
-  EXPECT_TRUE(section0_successful);
-  EXPECT_EQ(section0_expected, section0_actual);
-
-  bool section1_successful = ElfFileImpl32::ApplyOatPatches(
-      oat_patches.data(), oat_patches.data() + oat_patches.size(),
-      ".section1", delta,
-      section1_actual.data(), section1_actual.data() + section1_actual.size());
-  EXPECT_TRUE(section1_successful);
-  EXPECT_EQ(section1_expected, section1_actual);
-
-  bool section2_successful = ElfFileImpl32::ApplyOatPatches(
-      oat_patches.data(), oat_patches.data() + oat_patches.size(),
-      ".section2", delta,
-      section2_actual.data(), section2_actual.data() + section2_actual.size());
-  EXPECT_TRUE(section2_successful);
-  EXPECT_EQ(section2_expected, section2_actual);
 }
 
-#endif
-
 }  // namespace art
diff --git a/compiler/gc_map_builder.h b/compiler/gc_map_builder.h
index 4c36ef7..45e3fc5 100644
--- a/compiler/gc_map_builder.h
+++ b/compiler/gc_map_builder.h
@@ -19,8 +19,8 @@
 
 #include <vector>
 
+#include "base/bit_utils.h"
 #include "gc_map.h"
-#include "utils.h"
 
 namespace art {
 
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 195949b..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);
   }
 }
 
@@ -972,8 +1106,8 @@
   // Fix up the object previously had hash codes.
   for (const std::pair<mirror::Object*, uint32_t>& hash_pair : saved_hashes_) {
     Object* obj = hash_pair.first;
-    DCHECK_EQ(obj->GetLockWord(false).ReadBarrierState(), 0U);
-    obj->SetLockWord(LockWord::FromHashCode(hash_pair.second, 0U), false);
+    DCHECK_EQ(obj->GetLockWord<kVerifyNone>(false).ReadBarrierState(), 0U);
+    obj->SetLockWord<kVerifyNone>(LockWord::FromHashCode(hash_pair.second, 0U), false);
   }
   saved_hashes_.clear();
 }
@@ -984,58 +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_ == 4) {
-    // Will get fixed up by fixup object.
-    dst->SetClass(down_cast<mirror::Class*>(
-    GetImageAddress(mirror::IntArray::GetArrayClass())));
-  } else {
-    DCHECK_EQ(target_ptr_size_, 8u);
-    dst->SetClass(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_ == 4) {
-      down_cast<mirror::IntArray*>(dest_array)->SetWithoutChecks<kVerifyNone>(
-          i, static_cast<uint32_t>(reinterpret_cast<uint64_t>(fixup_location)));
-    } else {
-      down_cast<mirror::LongArray*>(dest_array)->SetWithoutChecks<kVerifyNone>(
-          i, reinterpret_cast<uint64_t>(fixup_location));
-    }
+    dest_array->SetElementPtrSize<false, true>(i, elem, target_ptr_size_);
   }
-  dst->SetLockWord(LockWord::Default(), false);
-  return true;
 }
 
 void ImageWriter::CopyAndFixupObject(Object* obj) {
@@ -1043,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);
 
@@ -1114,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);
@@ -1148,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);
 
@@ -1171,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();
@@ -1213,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:
@@ -1267,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_);
     }
   }
 }
@@ -1305,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);
@@ -1326,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 c0cffa5..a35d6ad 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -26,15 +26,16 @@
 #include <string>
 #include <ostream>
 
+#include "base/bit_utils.h"
 #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,
@@ -136,11 +136,14 @@
 
   friend std::ostream& operator<<(std::ostream& stream, const Bin& bin);
 
-  static constexpr size_t kBinBits = MinimumBitsToStore(kBinMirrorCount - 1);
+  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 7c400ee..d0a926f 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -16,8 +16,10 @@
 
 #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"
 #include "base/timing_logger.h"
 #include "compiler_callbacks.h"
 #include "dex/pass_manager.h"
@@ -26,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"
@@ -53,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);
@@ -73,8 +74,7 @@
       false,
       CompilerOptions::kDefaultTopKProfileThreshold,
       false,  // TODO: Think about debuggability of JIT-compiled code.
-      false,
-      false,
+      CompilerOptions::kDefaultGenerateDebugInfo,
       false,
       false,
       false,
@@ -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 eaf7872..dd4496f 100644
--- a/compiler/jni/jni_cfi_test_expected.inc
+++ b/compiler/jni/jni_cfi_test_expected.inc
@@ -84,14 +84,13 @@
     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, 0xF5, 0x03, 0x12, 0xAA,
-    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, 0xF2, 0x03, 0x15, 0xAA, 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, 0xEE, 0x3F, 0x45, 0x6D,
-    0xFF, 0x03, 0x03, 0x91, 0xC0, 0x03, 0x5F, 0xD6,
+    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,
+    0xEE, 0x3F, 0x45, 0x6D, 0xFF, 0x03, 0x03, 0x91, 0xC0, 0x03, 0x5F, 0xD6,
 };
 static constexpr uint8_t expected_cfi_kArm64[] = {
     0x44, 0x0E, 0xC0, 0x01, 0x44, 0x93, 0x18, 0x94, 0x16, 0x44, 0x95, 0x14,
@@ -99,15 +98,15 @@
     0x44, 0x9B, 0x08, 0x9C, 0x06, 0x44, 0x9D, 0x04, 0x9E, 0x02, 0x44, 0x05,
     0x48, 0x28, 0x05, 0x49, 0x26, 0x44, 0x05, 0x4A, 0x24, 0x05, 0x4B, 0x22,
     0x44, 0x05, 0x4C, 0x20, 0x05, 0x4D, 0x1E, 0x44, 0x05, 0x4E, 0x1C, 0x05,
-    0x4F, 0x1A, 0x5C, 0x0E, 0xE0, 0x01, 0x44, 0x0E, 0xC0, 0x01, 0x44, 0x0A,
-    0x44, 0xD3, 0xD4, 0x44, 0xD5, 0xD6, 0x44, 0xD7, 0xD8, 0x44, 0xD9, 0xDA,
-    0x44, 0xDB, 0xDC, 0x44, 0xDD, 0xDE, 0x44, 0x06, 0x48, 0x06, 0x49, 0x44,
-    0x06, 0x4A, 0x06, 0x4B, 0x44, 0x06, 0x4C, 0x06, 0x4D, 0x44, 0x06, 0x4E,
-    0x06, 0x4F, 0x44, 0x0E, 0x00, 0x44, 0x0B, 0x0E, 0xC0, 0x01,
+    0x4F, 0x1A, 0x58, 0x0E, 0xE0, 0x01, 0x44, 0x0E, 0xC0, 0x01, 0x0A, 0x44,
+    0xD3, 0xD4, 0x44, 0xD5, 0xD6, 0x44, 0xD7, 0xD8, 0x44, 0xD9, 0xDA, 0x44,
+    0xDB, 0xDC, 0x44, 0xDD, 0xDE, 0x44, 0x06, 0x48, 0x06, 0x49, 0x44, 0x06,
+    0x4A, 0x06, 0x4B, 0x44, 0x06, 0x4C, 0x06, 0x4D, 0x44, 0x06, 0x4E, 0x06,
+    0x4F, 0x44, 0x0E, 0x00, 0x44, 0x0B, 0x0E, 0xC0, 0x01,
 };
 // 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]
@@ -137,53 +136,51 @@
 // 0x00000028: stp d14, d15, [sp, #80]
 // 0x0000002c: .cfi_offset_extended: r78 at cfa-112
 // 0x0000002c: .cfi_offset_extended: r79 at cfa-104
-// 0x0000002c: mov x21, tr
-// 0x00000030: str w0, [sp]
-// 0x00000034: str w1, [sp, #196]
-// 0x00000038: str s0, [sp, #200]
-// 0x0000003c: str w2, [sp, #204]
-// 0x00000040: str w3, [sp, #208]
-// 0x00000044: sub sp, sp, #0x20 (32)
-// 0x00000048: .cfi_def_cfa_offset: 224
-// 0x00000048: add sp, sp, #0x20 (32)
-// 0x0000004c: .cfi_def_cfa_offset: 192
-// 0x0000004c: mov tr, x21
-// 0x00000050: .cfi_remember_state
-// 0x00000050: ldp x19, x20, [sp, #96]
-// 0x00000054: .cfi_restore: r19
-// 0x00000054: .cfi_restore: r20
-// 0x00000054: ldp x21, x22, [sp, #112]
-// 0x00000058: .cfi_restore: r21
-// 0x00000058: .cfi_restore: r22
-// 0x00000058: ldp x23, x24, [sp, #128]
-// 0x0000005c: .cfi_restore: r23
-// 0x0000005c: .cfi_restore: r24
-// 0x0000005c: ldp x25, x26, [sp, #144]
-// 0x00000060: .cfi_restore: r25
-// 0x00000060: .cfi_restore: r26
-// 0x00000060: ldp x27, x28, [sp, #160]
-// 0x00000064: .cfi_restore: r27
-// 0x00000064: .cfi_restore: r28
-// 0x00000064: ldp x29, lr, [sp, #176]
-// 0x00000068: .cfi_restore: r29
-// 0x00000068: .cfi_restore: r30
-// 0x00000068: ldp d8, d9, [sp, #32]
-// 0x0000006c: .cfi_restore_extended: r72
-// 0x0000006c: .cfi_restore_extended: r73
-// 0x0000006c: ldp d10, d11, [sp, #48]
-// 0x00000070: .cfi_restore_extended: r74
-// 0x00000070: .cfi_restore_extended: r75
-// 0x00000070: ldp d12, d13, [sp, #64]
-// 0x00000074: .cfi_restore_extended: r76
-// 0x00000074: .cfi_restore_extended: r77
-// 0x00000074: ldp d14, d15, [sp, #80]
-// 0x00000078: .cfi_restore_extended: r78
-// 0x00000078: .cfi_restore_extended: r79
-// 0x00000078: add sp, sp, #0xc0 (192)
-// 0x0000007c: .cfi_def_cfa_offset: 0
-// 0x0000007c: ret
-// 0x00000080: .cfi_restore_state
-// 0x00000080: .cfi_def_cfa_offset: 192
+// 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 tr, x20, [sp, #96]
+// 0x0000004c: .cfi_restore: r19
+// 0x0000004c: .cfi_restore: r20
+// 0x0000004c: ldp x21, x22, [sp, #112]
+// 0x00000050: .cfi_restore: r21
+// 0x00000050: .cfi_restore: r22
+// 0x00000050: ldp x23, x24, [sp, #128]
+// 0x00000054: .cfi_restore: r23
+// 0x00000054: .cfi_restore: r24
+// 0x00000054: ldp x25, x26, [sp, #144]
+// 0x00000058: .cfi_restore: r25
+// 0x00000058: .cfi_restore: r26
+// 0x00000058: ldp x27, x28, [sp, #160]
+// 0x0000005c: .cfi_restore: r27
+// 0x0000005c: .cfi_restore: r28
+// 0x0000005c: ldp x29, lr, [sp, #176]
+// 0x00000060: .cfi_restore: r29
+// 0x00000060: .cfi_restore: r30
+// 0x00000060: ldp d8, d9, [sp, #32]
+// 0x00000064: .cfi_restore_extended: r72
+// 0x00000064: .cfi_restore_extended: r73
+// 0x00000064: ldp d10, d11, [sp, #48]
+// 0x00000068: .cfi_restore_extended: r74
+// 0x00000068: .cfi_restore_extended: r75
+// 0x00000068: ldp d12, d13, [sp, #64]
+// 0x0000006c: .cfi_restore_extended: r76
+// 0x0000006c: .cfi_restore_extended: r77
+// 0x0000006c: ldp d14, d15, [sp, #80]
+// 0x00000070: .cfi_restore_extended: r78
+// 0x00000070: .cfi_restore_extended: r79
+// 0x00000070: add sp, sp, #0xc0 (192)
+// 0x00000074: .cfi_def_cfa_offset: 0
+// 0x00000074: ret
+// 0x00000078: .cfi_restore_state
+// 0x00000078: .cfi_def_cfa_offset: 192
 
 static constexpr uint8_t expected_asm_kX86[] = {
     0x57, 0x56, 0x55, 0x83, 0xC4, 0xE4, 0x50, 0x89, 0x4C, 0x24, 0x34, 0xF3,
@@ -238,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,
@@ -285,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,
@@ -400,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
@@ -409,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,
@@ -445,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
@@ -479,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 a6caff1..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;
 }
@@ -158,7 +158,8 @@
                                                      const char* shorty)
     : JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
   uint32_t core_spill_mask = CoreSpillMask();
-  for (int x_reg = 0; x_reg < kNumberOfXRegisters; ++x_reg) {
+  DCHECK_EQ(XZR, kNumberOfXRegisters - 1);  // Exclude XZR from the loop (avoid 1 << 32).
+  for (int x_reg = 0; x_reg < kNumberOfXRegisters - 1; ++x_reg) {
     if (((1 << x_reg) & core_spill_mask) != 0) {
       callee_save_regs_.push_back(
           Arm64ManagedRegister::FromXRegister(static_cast<XRegister>(x_reg)));
@@ -183,7 +184,7 @@
   // Jni function is the native function which the java code wants to call.
   // Jni method is the method that compiled by jni compiler.
   // Call chain: managed code(java) --> jni method --> jni function.
-  // Thread register(X18, scratched by aapcs64) is not saved on stack, it is saved in ETR(X21).
+  // Thread register(X19) is saved on stack.
   return 1 << X19 | 1 << X20 | 1 << X21 | 1 << X22 | 1 << X23 | 1 << X24 |
          1 << X25 | 1 << X26 | 1 << X27 | 1 << X28 | 1 << X29 | 1 << LR;
 }
@@ -205,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 436fc0c..bb8136b 100644
--- a/compiler/jni/quick/calling_convention.cc
+++ b/compiler/jni/quick/calling_convention.cc
@@ -23,7 +23,6 @@
 #include "jni/quick/mips64/calling_convention_mips64.h"
 #include "jni/quick/x86/calling_convention_x86.h"
 #include "jni/quick/x86_64/calling_convention_x86_64.h"
-#include "utils.h"
 
 namespace art {
 
@@ -132,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 {
@@ -229,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 a06303d..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"
@@ -94,7 +94,7 @@
 
   // Assembler that holds generated instructions
   std::unique_ptr<Assembler> jni_asm(Assembler::Create(instruction_set));
-  jni_asm->cfi().SetEnabled(driver->GetCompilerOptions().GetIncludeCFI());
+  jni_asm->cfi().SetEnabled(driver->GetCompilerOptions().GetGenerateDebugInfo());
 
   // Offsets into data structures
   // TODO: if cross compiling these offsets are for the host not the target
@@ -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 8a45f0c..322caca 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.cc
+++ b/compiler/jni/quick/x86/calling_convention_x86.cc
@@ -19,7 +19,6 @@
 #include "base/logging.h"
 #include "handle_scope-inl.h"
 #include "utils/x86/managed_register_x86.h"
-#include "utils.h"
 
 namespace art {
 namespace x86 {
@@ -181,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 bbdf1fe..9c7eab1 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
@@ -16,10 +16,10 @@
 
 #include "calling_convention_x86_64.h"
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "handle_scope-inl.h"
 #include "utils/x86_64/managed_register_x86_64.h"
-#include "utils.h"
 
 namespace art {
 namespace x86_64 {
@@ -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 15b4017..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"
@@ -351,9 +351,8 @@
  public:
   InitCodeMethodVisitor(OatWriter* writer, size_t offset)
     : OatDexMethodVisitor(writer, offset),
-      text_absolute_patch_locations_(writer->GetAbsolutePatchLocationsFor(".text")),
       debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()) {
-    text_absolute_patch_locations_->reserve(
+    writer_->absolute_patch_locations_.reserve(
         writer_->compiler_driver_->GetNonRelativeLinkerPatchCount());
   }
 
@@ -444,14 +443,13 @@
           uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset();
           for (const LinkerPatch& patch : compiled_method->GetPatches()) {
             if (!patch.IsPcRelative()) {
-              text_absolute_patch_locations_->push_back(base_loc + patch.LiteralOffset());
+              writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset());
             }
           }
         }
       }
 
-      if (writer_->compiler_driver_->GetCompilerOptions().GetIncludeDebugSymbols() ||
-          writer_->compiler_driver_->GetCompilerOptions().GetIncludeCFI()) {
+      if (writer_->compiler_driver_->GetCompilerOptions().GetGenerateDebugInfo()) {
         // Record debug information for this function if we are doing that.
         const uint32_t quick_code_start = quick_code_offset -
             writer_->oat_header_->GetExecutableOffset() - thumb_offset;
@@ -547,9 +545,6 @@
   // so we can simply compare the pointers to find out if things are duplicated.
   SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
 
-  // Patch locations for the .text section.
-  std::vector<uintptr_t>* const text_absolute_patch_locations_;
-
   // Cache of compiler's --debuggable option.
   const bool debuggable_;
 };
@@ -620,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);
@@ -755,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);
@@ -794,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;
   }
@@ -810,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);
@@ -865,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/oat_writer.h b/compiler/oat_writer.h
index 6f1b4ec..82b9377 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -19,7 +19,6 @@
 
 #include <stdint.h>
 #include <cstddef>
-#include <map>
 #include <memory>
 
 #include "linker/relative_patcher.h"  // For linker::RelativePatcherTargetProvider.
@@ -82,8 +81,6 @@
 //
 class OatWriter {
  public:
-  typedef std::map<std::string, std::unique_ptr<std::vector<uintptr_t>>> PatchLocationsMap;
-
   OatWriter(const std::vector<const DexFile*>& dex_files,
             uint32_t image_file_location_oat_checksum,
             uintptr_t image_file_location_oat_begin,
@@ -105,19 +102,10 @@
     return bss_size_;
   }
 
-  const PatchLocationsMap& GetAbsolutePatchLocations() const {
+  const std::vector<uintptr_t>& GetAbsolutePatchLocations() const {
     return absolute_patch_locations_;
   }
 
-  std::vector<uintptr_t>* GetAbsolutePatchLocationsFor(const char* section_name) {
-    auto it = absolute_patch_locations_.emplace(
-        std::string(section_name), std::unique_ptr<std::vector<uintptr_t>>());
-    if (it.second) {  // Inserted new item.
-      it.first->second.reset(new std::vector<uintptr_t>());
-    }
-    return it.first->second.get();
-  }
-
   bool WriteRodata(OutputStream* out);
   bool WriteCode(OutputStream* out);
 
@@ -339,9 +327,8 @@
 
   std::unique_ptr<linker::RelativePatcher> relative_patcher_;
 
-  // The locations of absolute patches relative to the start of section.
-  // The map's key is the ELF's section name (including the dot).
-  PatchLocationsMap absolute_patch_locations_;
+  // The locations of absolute patches relative to the start of the executable section.
+  std::vector<uintptr_t> absolute_patch_locations_;
 
   // Map method reference to assigned offset.
   // Wrap the map in a class implementing linker::RelativePatcherTargetProvider.
diff --git a/compiler/optimizing/bounds_check_elimination_test.cc b/compiler/optimizing/bounds_check_elimination_test.cc
index 163458f..48090a3 100644
--- a/compiler/optimizing/bounds_check_elimination_test.cc
+++ b/compiler/optimizing/bounds_check_elimination_test.cc
@@ -647,7 +647,7 @@
   graph->AddBlock(block);
   entry->AddSuccessor(block);
   HInstruction* new_array = new (allocator)
-      HNewArray(constant_10, 0, Primitive::kPrimInt, kQuickAllocArray);
+      HNewArray(constant_10, 0, Primitive::kPrimInt, graph->GetDexFile(), kQuickAllocArray);
   block->AddInstruction(new_array);
   block->AddInstruction(new (allocator) HGoto());
 
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index c4eaabf..f98029d 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -652,8 +652,8 @@
     DCHECK((optimized_invoke_type == invoke_type) || (optimized_invoke_type != kDirect)
            || compiler_driver_->GetCompilerOptions().GetCompilePic());
     bool is_recursive =
-        (target_method.dex_method_index == dex_compilation_unit_->GetDexMethodIndex());
-    DCHECK(!is_recursive || (target_method.dex_file == dex_compilation_unit_->GetDexFile()));
+        (target_method.dex_method_index == outer_compilation_unit_->GetDexMethodIndex())
+        && (target_method.dex_file == outer_compilation_unit_->GetDexFile());
 
     if (optimized_invoke_type == kStatic) {
       ScopedObjectAccess soa(Thread::Current());
@@ -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);
@@ -711,8 +710,12 @@
           clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
         } else {
           clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit;
-          HLoadClass* load_class =
-              new (arena_) HLoadClass(storage_index, is_referrer_class, dex_pc);
+          HLoadClass* load_class = new (arena_) HLoadClass(
+              graph_->GetCurrentMethod(),
+              storage_index,
+              *dex_compilation_unit_->GetDexFile(),
+              is_referrer_class,
+              dex_pc);
           current_block_->AddInstruction(load_class);
           clinit_check = new (arena_) HClinitCheck(load_class, dex_pc);
           current_block_->AddInstruction(clinit_check);
@@ -824,13 +827,17 @@
         value,
         field_type,
         resolved_field->GetOffset(),
-        resolved_field->IsVolatile()));
+        resolved_field->IsVolatile(),
+        field_index,
+        *dex_file_));
   } else {
     current_block_->AddInstruction(new (arena_) HInstanceFieldGet(
         current_block_->GetLastInstruction(),
         field_type,
         resolved_field->GetOffset(),
-        resolved_field->IsVolatile()));
+        resolved_field->IsVolatile(),
+        field_index,
+        *dex_file_));
 
     UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
   }
@@ -915,7 +922,11 @@
       *outer_compilation_unit_->GetDexFile(), storage_index);
   bool is_initialized = resolved_field->GetDeclaringClass()->IsInitialized() && is_in_dex_cache;
 
-  HLoadClass* constant = new (arena_) HLoadClass(storage_index, is_referrer_class, dex_pc);
+  HLoadClass* constant = new (arena_) HLoadClass(graph_->GetCurrentMethod(),
+                                                 storage_index,
+                                                 *dex_compilation_unit_->GetDexFile(),
+                                                 is_referrer_class,
+                                                 dex_pc);
   current_block_->AddInstruction(constant);
 
   HInstruction* cls = constant;
@@ -931,13 +942,20 @@
     temps.Add(cls);
     HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
     DCHECK_EQ(value->GetType(), field_type);
-    current_block_->AddInstruction(
-        new (arena_) HStaticFieldSet(cls, value, field_type, resolved_field->GetOffset(),
-            resolved_field->IsVolatile()));
+    current_block_->AddInstruction(new (arena_) HStaticFieldSet(cls,
+                                                                value,
+                                                                field_type,
+                                                                resolved_field->GetOffset(),
+                                                                resolved_field->IsVolatile(),
+                                                                field_index,
+                                                                *dex_file_));
   } else {
-    current_block_->AddInstruction(
-        new (arena_) HStaticFieldGet(cls, field_type, resolved_field->GetOffset(),
-            resolved_field->IsVolatile()));
+    current_block_->AddInstruction(new (arena_) HStaticFieldGet(cls,
+                                                                field_type,
+                                                                resolved_field->GetOffset(),
+                                                                resolved_field->IsVolatile(),
+                                                                field_index,
+                                                                *dex_file_));
     UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
   }
   return true;
@@ -1026,7 +1044,11 @@
   QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
       ? kQuickAllocArrayWithAccessCheck
       : kQuickAllocArray;
-  HInstruction* object = new (arena_) HNewArray(length, dex_pc, type_index, entrypoint);
+  HInstruction* object = new (arena_) HNewArray(length,
+                                                dex_pc,
+                                                type_index,
+                                                *dex_compilation_unit_->GetDexFile(),
+                                                entrypoint);
   current_block_->AddInstruction(object);
 
   const char* descriptor = dex_file_->StringByTypeIdx(type_index);
@@ -1151,7 +1173,11 @@
   }
   HInstruction* object = LoadLocal(reference, Primitive::kPrimNot);
   HLoadClass* cls = new (arena_) HLoadClass(
-      type_index, IsOutermostCompilingClass(type_index), dex_pc);
+      graph_->GetCurrentMethod(),
+      type_index,
+      *dex_compilation_unit_->GetDexFile(),
+      IsOutermostCompilingClass(type_index),
+      dex_pc);
   current_block_->AddInstruction(cls);
   // The class needs a temporary before being used by the type check.
   Temporaries temps(graph_);
@@ -1976,7 +2002,8 @@
             ? kQuickAllocObjectWithAccessCheck
             : kQuickAllocObject;
 
-        current_block_->AddInstruction(new (arena_) HNewInstance(dex_pc, type_index, entrypoint));
+        current_block_->AddInstruction(new (arena_) HNewInstance(
+            dex_pc, type_index, *dex_compilation_unit_->GetDexFile(), entrypoint));
         UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
       }
       break;
@@ -1988,8 +2015,8 @@
       QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
           ? kQuickAllocArrayWithAccessCheck
           : kQuickAllocArray;
-      current_block_->AddInstruction(
-          new (arena_) HNewArray(length, dex_pc, type_index, entrypoint));
+      current_block_->AddInstruction(new (arena_) HNewArray(
+          length, dex_pc, type_index, *dex_compilation_unit_->GetDexFile(), entrypoint));
       UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
       break;
     }
@@ -2134,13 +2161,15 @@
     }
 
     case Instruction::CONST_STRING: {
-      current_block_->AddInstruction(new (arena_) HLoadString(instruction.VRegB_21c(), dex_pc));
+      current_block_->AddInstruction(
+          new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_21c(), dex_pc));
       UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
       break;
     }
 
     case Instruction::CONST_STRING_JUMBO: {
-      current_block_->AddInstruction(new (arena_) HLoadString(instruction.VRegB_31c(), dex_pc));
+      current_block_->AddInstruction(
+          new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_31c(), dex_pc));
       UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction());
       break;
     }
@@ -2161,8 +2190,12 @@
         MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
         return false;
       }
-      current_block_->AddInstruction(
-          new (arena_) HLoadClass(type_index, IsOutermostCompilingClass(type_index), dex_pc));
+      current_block_->AddInstruction(new (arena_) HLoadClass(
+          graph_->GetCurrentMethod(),
+          type_index,
+          *dex_compilation_unit_->GetDexFile(),
+          IsOutermostCompilingClass(type_index),
+          dex_pc));
       UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
       break;
     }
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 4805cee..0cd63a6 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -114,18 +114,24 @@
   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) {
     MarkNotLeaf();
   }
+  const bool is_64_bit = Is64BitInstructionSet(GetInstructionSet());
   InitializeCodeGeneration(GetGraph()->GetNumberOfLocalVRegs()
                              + GetGraph()->GetTemporariesVRegSlots()
                              + 1 /* filler */,
                            0, /* the baseline compiler does not have live registers at slow path */
                            0, /* the baseline compiler does not have live registers at slow path */
                            GetGraph()->GetMaximumNumberOfOutVRegs()
-                             + 1 /* current method */,
+                             + (is_64_bit ? 2 : 1) /* current method */,
                            GetGraph()->GetBlocks());
   CompileInternal(allocator, /* is_baseline */ true);
 }
@@ -270,7 +276,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.
@@ -702,8 +709,10 @@
   if (environment->GetParent() != nullptr) {
     // We emit the parent environment first.
     EmitEnvironment(environment->GetParent(), slow_path);
-    stack_map_stream_.BeginInlineInfoEntry(
-        environment->GetMethodIdx(), environment->GetDexPc(), environment->Size());
+    stack_map_stream_.BeginInlineInfoEntry(environment->GetMethodIdx(),
+                                           environment->GetDexPc(),
+                                           environment->GetInvokeType(),
+                                           environment->Size());
   }
 
   // Walk over the environment, and record the location of dex registers.
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 7a0c9c1..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"
@@ -41,6 +41,7 @@
 }
 
 static constexpr int kCurrentMethodStackOffset = 0;
+static constexpr Register kMethodRegisterArgument = R0;
 
 // We unconditionally allocate R5 to ensure we can do long operations
 // with baseline.
@@ -494,11 +495,6 @@
         assembler_(codegen->GetAssembler()),
         codegen_(codegen) {}
 
-static uint32_t LeastSignificantBit(uint32_t mask) {
-  // ffs starts at 1.
-  return ffs(mask) - 1;
-}
-
 void CodeGeneratorARM::ComputeSpillMask() {
   core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_;
   // Save one extra register for baseline. Note that on thumb2, there is no easy
@@ -549,7 +545,7 @@
   uint32_t push_mask = (core_spill_mask_ & (~(1 << PC))) | 1 << LR;
   __ PushList(push_mask);
   __ cfi().AdjustCFAOffset(kArmWordSize * POPCOUNT(push_mask));
-  __ cfi().RelOffsetForMany(DWARFReg(R0), 0, push_mask, kArmWordSize);
+  __ cfi().RelOffsetForMany(DWARFReg(kMethodRegisterArgument), 0, push_mask, kArmWordSize);
   if (fpu_spill_mask_ != 0) {
     SRegister start_register = SRegister(LeastSignificantBit(fpu_spill_mask_));
     __ vpushs(start_register, POPCOUNT(fpu_spill_mask_));
@@ -559,7 +555,7 @@
   int adjust = GetFrameSize() - FrameEntrySpillSize();
   __ AddConstant(SP, -adjust);
   __ cfi().AdjustCFAOffset(adjust);
-  __ StoreToOffset(kStoreWord, R0, SP, 0);
+  __ StoreToOffset(kStoreWord, kMethodRegisterArgument, SP, 0);
 }
 
 void CodeGeneratorARM::GenerateFrameExit() {
@@ -808,11 +804,11 @@
 
 void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
   LocationSummary* locations = instruction->GetLocations();
-  if (locations != nullptr && locations->Out().Equals(location)) {
+  if (instruction->IsCurrentMethod()) {
+    Move32(location, Location::StackSlot(kCurrentMethodStackOffset));
+  } else if (locations != nullptr && locations->Out().Equals(location)) {
     return;
-  }
-
-  if (locations != nullptr && locations->Out().IsConstant()) {
+  } else if (locations != nullptr && locations->Out().IsConstant()) {
     HConstant* const_to_move = locations->Out().GetConstant();
     if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) {
       int32_t value = GetInt32ValueOf(const_to_move);
@@ -1033,19 +1029,19 @@
   GenerateTestAndBranch(deoptimize, slow_path_entry, nullptr, slow_path_entry);
 }
 
-void LocationsBuilderARM::VisitCondition(HCondition* comp) {
+void LocationsBuilderARM::VisitCondition(HCondition* cond) {
   LocationSummary* locations =
-      new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
+      new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RequiresRegister());
-  locations->SetInAt(1, Location::RegisterOrConstant(comp->InputAt(1)));
-  if (comp->NeedsMaterialization()) {
+  locations->SetInAt(1, Location::RegisterOrConstant(cond->InputAt(1)));
+  if (cond->NeedsMaterialization()) {
     locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
   }
 }
 
-void InstructionCodeGeneratorARM::VisitCondition(HCondition* comp) {
-  if (!comp->NeedsMaterialization()) return;
-  LocationSummary* locations = comp->GetLocations();
+void InstructionCodeGeneratorARM::VisitCondition(HCondition* cond) {
+  if (!cond->NeedsMaterialization()) return;
+  LocationSummary* locations = cond->GetLocations();
   Register left = locations->InAt(0).AsRegister<Register>();
 
   if (locations->InAt(1).IsRegister()) {
@@ -1062,11 +1058,11 @@
       __ cmp(left, ShifterOperand(temp));
     }
   }
-  __ it(ARMCondition(comp->GetCondition()), kItElse);
+  __ it(ARMCondition(cond->GetCondition()), kItElse);
   __ mov(locations->Out().AsRegister<Register>(), ShifterOperand(1),
-         ARMCondition(comp->GetCondition()));
+         ARMCondition(cond->GetCondition()));
   __ mov(locations->Out().AsRegister<Register>(), ShifterOperand(0),
-         ARMOppositeCondition(comp->GetCondition()));
+         ARMOppositeCondition(cond->GetCondition()));
 }
 
 void LocationsBuilderARM::VisitEqual(HEqual* comp) {
@@ -1291,7 +1287,7 @@
 void LocationsBuilderARM::HandleInvoke(HInvoke* invoke) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(invoke, LocationSummary::kCall);
-  locations->AddTemp(Location::RegisterLocation(R0));
+  locations->AddTemp(Location::RegisterLocation(kMethodRegisterArgument));
 
   InvokeDexCallingConventionVisitorARM calling_convention_visitor;
   for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) {
@@ -1318,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();
@@ -1332,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();
@@ -1352,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();
@@ -1371,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();
@@ -2222,7 +2218,7 @@
   Register dividend = locations->InAt(0).AsRegister<Register>();
   Register temp = locations->GetTemp(0).AsRegister<Register>();
   int32_t imm = second.GetConstant()->AsIntConstant()->GetValue();
-  int32_t abs_imm = std::abs(imm);
+  uint32_t abs_imm = static_cast<uint32_t>(std::abs(imm));
   DCHECK(IsPowerOfTwo(abs_imm));
   int ctz_imm = CTZ(abs_imm);
 
@@ -2807,9 +2803,19 @@
   locations->SetOut(location);
 }
 
-void InstructionCodeGeneratorARM::VisitParameterValue(HParameterValue* instruction) {
+void InstructionCodeGeneratorARM::VisitParameterValue(
+    HParameterValue* instruction ATTRIBUTE_UNUSED) {
   // Nothing to do, the parameter is already at its location.
-  UNUSED(instruction);
+}
+
+void LocationsBuilderARM::VisitCurrentMethod(HCurrentMethod* instruction) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+  locations->SetOut(Location::RegisterLocation(kMethodRegisterArgument));
+}
+
+void InstructionCodeGeneratorARM::VisitCurrentMethod(HCurrentMethod* instruction ATTRIBUTE_UNUSED) {
+  // Nothing to do, the method is already at its location.
 }
 
 void LocationsBuilderARM::VisitNot(HNot* not_) {
@@ -3959,21 +3965,25 @@
       : LocationSummary::kNoCall;
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(cls, call_kind);
+  locations->SetInAt(0, Location::RequiresRegister());
   locations->SetOut(Location::RequiresRegister());
 }
 
 void InstructionCodeGeneratorARM::VisitLoadClass(HLoadClass* cls) {
-  Register out = cls->GetLocations()->Out().AsRegister<Register>();
+  LocationSummary* locations = cls->GetLocations();
+  Register out = locations->Out().AsRegister<Register>();
+  Register current_method = locations->InAt(0).AsRegister<Register>();
   if (cls->IsReferrersClass()) {
     DCHECK(!cls->CanCallRuntime());
     DCHECK(!cls->MustGenerateClinitCheck());
-    codegen_->LoadCurrentMethod(out);
-    __ LoadFromOffset(kLoadWord, out, out, mirror::ArtMethod::DeclaringClassOffset().Int32Value());
+    __ LoadFromOffset(
+        kLoadWord, out, current_method, ArtMethod::DeclaringClassOffset().Int32Value());
   } else {
     DCHECK(cls->CanCallRuntime());
-    codegen_->LoadCurrentMethod(out);
-    __ LoadFromOffset(
-        kLoadWord, out, out, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value());
+    __ LoadFromOffset(kLoadWord,
+                      out,
+                      current_method,
+                      ArtMethod::DexCacheResolvedTypesOffset().Int32Value());
     __ LoadFromOffset(kLoadWord, out, out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex()));
 
     SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM(
@@ -4021,6 +4031,7 @@
 void LocationsBuilderARM::VisitLoadString(HLoadString* load) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kCallOnSlowPath);
+  locations->SetInAt(0, Location::RequiresRegister());
   locations->SetOut(Location::RequiresRegister());
 }
 
@@ -4028,9 +4039,11 @@
   SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathARM(load);
   codegen_->AddSlowPath(slow_path);
 
-  Register out = load->GetLocations()->Out().AsRegister<Register>();
-  codegen_->LoadCurrentMethod(out);
-  __ LoadFromOffset(kLoadWord, out, out, mirror::ArtMethod::DeclaringClassOffset().Int32Value());
+  LocationSummary* locations = load->GetLocations();
+  Register out = locations->Out().AsRegister<Register>();
+  Register current_method = locations->InAt(0).AsRegister<Register>();
+  __ LoadFromOffset(
+      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));
@@ -4148,7 +4161,9 @@
   __ cmp(temp, ShifterOperand(cls));
   __ b(slow_path->GetEntryLabel(), NE);
   __ Bind(slow_path->GetExitLabel());
-  __ Bind(&done);
+  if (instruction->MustDoNullCheck()) {
+    __ Bind(&done);
+  }
 }
 
 void LocationsBuilderARM::VisitMonitorOperation(HMonitorOperation* instruction) {
@@ -4253,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);
@@ -4263,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 b6d99ab..40432e4 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) {
@@ -634,16 +633,16 @@
                               Location location,
                               HInstruction* move_for) {
   LocationSummary* locations = instruction->GetLocations();
-  if (locations != nullptr && locations->Out().Equals(location)) {
-    return;
-  }
-
   Primitive::Type type = instruction->GetType();
   DCHECK_NE(type, Primitive::kPrimVoid);
 
-  if (instruction->IsIntConstant()
-      || instruction->IsLongConstant()
-      || instruction->IsNullConstant()) {
+  if (instruction->IsCurrentMethod()) {
+    MoveLocation(location, Location::DoubleStackSlot(kCurrentMethodStackOffset));
+  } else if (locations != nullptr && locations->Out().Equals(location)) {
+    return;
+  } else if (instruction->IsIntConstant()
+             || instruction->IsLongConstant()
+             || instruction->IsNullConstant()) {
     int64_t value = GetInt64ValueOf(instruction->AsConstant());
     if (location.IsRegister()) {
       Register dst = RegisterFrom(location, type);
@@ -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));
 }
 
@@ -1738,7 +1737,7 @@
   Register out = OutputRegister(instruction);
   Register dividend = InputRegisterAt(instruction, 0);
   int64_t imm = Int64FromConstant(second.GetConstant());
-  int64_t abs_imm = std::abs(imm);
+  uint64_t abs_imm = static_cast<uint64_t>(std::abs(imm));
   DCHECK(IsPowerOfTwo(abs_imm));
   int ctz_imm = CTZ(abs_imm);
 
@@ -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());
@@ -2345,20 +2344,20 @@
   LocationSummary::CallKind call_kind = cls->CanCallRuntime() ? LocationSummary::kCallOnSlowPath
                                                               : LocationSummary::kNoCall;
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(cls, call_kind);
+  locations->SetInAt(0, Location::RequiresRegister());
   locations->SetOut(Location::RequiresRegister());
 }
 
 void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) {
   Register out = OutputRegister(cls);
+  Register current_method = InputRegisterAt(cls, 0);
   if (cls->IsReferrersClass()) {
     DCHECK(!cls->CanCallRuntime());
     DCHECK(!cls->MustGenerateClinitCheck());
-    codegen_->LoadCurrentMethod(out);
-    __ Ldr(out, HeapOperand(out, mirror::ArtMethod::DeclaringClassOffset()));
+    __ Ldr(out, MemOperand(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
   } else {
     DCHECK(cls->CanCallRuntime());
-    codegen_->LoadCurrentMethod(out);
-    __ Ldr(out, HeapOperand(out, 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(
@@ -2397,6 +2396,7 @@
 void LocationsBuilderARM64::VisitLoadString(HLoadString* load) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kCallOnSlowPath);
+  locations->SetInAt(0, Location::RequiresRegister());
   locations->SetOut(Location::RequiresRegister());
 }
 
@@ -2405,8 +2405,8 @@
   codegen_->AddSlowPath(slow_path);
 
   Register out = OutputRegister(load);
-  codegen_->LoadCurrentMethod(out);
-  __ Ldr(out, HeapOperand(out, mirror::ArtMethod::DeclaringClassOffset()));
+  Register current_method = InputRegisterAt(load, 0);
+  __ 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());
@@ -2534,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) {
@@ -2542,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) {
@@ -2562,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) {
@@ -2571,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) {
@@ -2674,9 +2673,20 @@
   locations->SetOut(location);
 }
 
-void InstructionCodeGeneratorARM64::VisitParameterValue(HParameterValue* instruction) {
+void InstructionCodeGeneratorARM64::VisitParameterValue(
+    HParameterValue* instruction ATTRIBUTE_UNUSED) {
   // Nothing to do, the parameter is already at its location.
-  UNUSED(instruction);
+}
+
+void LocationsBuilderARM64::VisitCurrentMethod(HCurrentMethod* instruction) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+  locations->SetOut(LocationFrom(x0));
+}
+
+void InstructionCodeGeneratorARM64::VisitCurrentMethod(
+    HCurrentMethod* instruction ATTRIBUTE_UNUSED) {
+  // Nothing to do, the method is already at its location.
 }
 
 void LocationsBuilderARM64::VisitPhi(HPhi* instruction) {
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index b56ca10..7a502e0 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -44,18 +44,18 @@
 };
 static constexpr size_t kParameterFPRegistersLength = arraysize(kParameterFPRegisters);
 
-const vixl::Register tr = vixl::x18;                        // Thread Register
-static const vixl::Register kArtMethodRegister = vixl::w0;  // Method register on invoke.
+const vixl::Register tr = vixl::x19;                        // Thread Register
+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);
 
 const vixl::CPURegList runtime_reserved_core_registers(tr, vixl::lr);
 
-// Callee-saved registers defined by AAPCS64.
+// Callee-saved registers AAPCS64 (without x19 - Thread Register)
 const vixl::CPURegList callee_saved_core_registers(vixl::CPURegister::kRegister,
                                                    vixl::kXRegSize,
-                                                   vixl::x19.code(),
+                                                   vixl::x20.code(),
                                                    vixl::x30.code());
 const vixl::CPURegList callee_saved_fp_registers(vixl::CPURegister::kFPRegister,
                                                  vixl::kDRegSize,
@@ -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 a6f01da..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"
@@ -36,6 +36,7 @@
 namespace x86 {
 
 static constexpr int kCurrentMethodStackOffset = 0;
+static constexpr Register kMethodRegisterArgument = EAX;
 
 static constexpr Register kCoreCalleeSaves[] = { EBP, ESI, EDI };
 
@@ -498,7 +499,7 @@
   int adjust = GetFrameSize() - FrameEntrySpillSize();
   __ subl(ESP, Immediate(adjust));
   __ cfi().AdjustCFAOffset(adjust);
-  __ movl(Address(ESP, kCurrentMethodStackOffset), EAX);
+  __ movl(Address(ESP, kCurrentMethodStackOffset), kMethodRegisterArgument);
 }
 
 void CodeGeneratorX86::GenerateFrameExit() {
@@ -717,11 +718,11 @@
 
 void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
   LocationSummary* locations = instruction->GetLocations();
-  if (locations != nullptr && locations->Out().Equals(location)) {
+  if (instruction->IsCurrentMethod()) {
+    Move32(location, Location::StackSlot(kCurrentMethodStackOffset));
+  } else if (locations != nullptr && locations->Out().Equals(location)) {
     return;
-  }
-
-  if (locations != nullptr && locations->Out().IsConstant()) {
+  } else if (locations != nullptr && locations->Out().IsConstant()) {
     HConstant* const_to_move = locations->Out().GetConstant();
     if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) {
       Immediate imm(GetInt32ValueOf(const_to_move));
@@ -983,20 +984,20 @@
   UNUSED(store);
 }
 
-void LocationsBuilderX86::VisitCondition(HCondition* comp) {
+void LocationsBuilderX86::VisitCondition(HCondition* cond) {
   LocationSummary* locations =
-      new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
+      new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, Location::Any());
-  if (comp->NeedsMaterialization()) {
+  if (cond->NeedsMaterialization()) {
     // We need a byte register.
     locations->SetOut(Location::RegisterLocation(ECX));
   }
 }
 
-void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) {
-  if (comp->NeedsMaterialization()) {
-    LocationSummary* locations = comp->GetLocations();
+void InstructionCodeGeneratorX86::VisitCondition(HCondition* cond) {
+  if (cond->NeedsMaterialization()) {
+    LocationSummary* locations = cond->GetLocations();
     Register reg = locations->Out().AsRegister<Register>();
     // Clear register: setcc only sets the low byte.
     __ xorl(reg, reg);
@@ -1014,7 +1015,7 @@
     } else {
       __ cmpl(lhs.AsRegister<Register>(), Address(ESP, rhs.GetStackIndex()));
     }
-    __ setb(X86Condition(comp->GetCondition()), reg);
+    __ setb(X86Condition(cond->GetCondition()), reg);
   }
 }
 
@@ -1239,7 +1240,7 @@
 void LocationsBuilderX86::HandleInvoke(HInvoke* invoke) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(invoke, LocationSummary::kCall);
-  locations->AddTemp(Location::RegisterLocation(EAX));
+  locations->AddTemp(Location::RegisterLocation(kMethodRegisterArgument));
 
   InvokeDexCallingConventionVisitorX86 calling_convention_visitor;
   for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) {
@@ -1275,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();
@@ -1292,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());
@@ -1307,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();
@@ -1328,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());
@@ -1959,6 +1960,8 @@
       if (second.IsRegister()) {
         if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
           __ addl(out.AsRegister<Register>(), second.AsRegister<Register>());
+        } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
+          __ addl(out.AsRegister<Register>(), first.AsRegister<Register>());
         } else {
           __ leal(out.AsRegister<Register>(), Address(
               first.AsRegister<Register>(), second.AsRegister<Register>(), TIMES_1, 0));
@@ -3010,8 +3013,17 @@
   locations->SetOut(location);
 }
 
-void InstructionCodeGeneratorX86::VisitParameterValue(HParameterValue* instruction) {
-  UNUSED(instruction);
+void InstructionCodeGeneratorX86::VisitParameterValue(
+    HParameterValue* instruction ATTRIBUTE_UNUSED) {
+}
+
+void LocationsBuilderX86::VisitCurrentMethod(HCurrentMethod* instruction) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+  locations->SetOut(Location::RegisterLocation(kMethodRegisterArgument));
+}
+
+void InstructionCodeGeneratorX86::VisitCurrentMethod(HCurrentMethod* instruction ATTRIBUTE_UNUSED) {
 }
 
 void LocationsBuilderX86::VisitNot(HNot* not_) {
@@ -3207,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());
     }
@@ -4279,20 +4292,22 @@
       : LocationSummary::kNoCall;
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(cls, call_kind);
+  locations->SetInAt(0, Location::RequiresRegister());
   locations->SetOut(Location::RequiresRegister());
 }
 
 void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) {
-  Register out = cls->GetLocations()->Out().AsRegister<Register>();
+  LocationSummary* locations = cls->GetLocations();
+  Register out = locations->Out().AsRegister<Register>();
+  Register current_method = locations->InAt(0).AsRegister<Register>();
   if (cls->IsReferrersClass()) {
     DCHECK(!cls->CanCallRuntime());
     DCHECK(!cls->MustGenerateClinitCheck());
-    codegen_->LoadCurrentMethod(out);
-    __ movl(out, Address(out, mirror::ArtMethod::DeclaringClassOffset().Int32Value()));
+    __ movl(out, Address(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
   } else {
     DCHECK(cls->CanCallRuntime());
-    codegen_->LoadCurrentMethod(out);
-    __ movl(out, Address(out, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value()));
+    __ movl(out, Address(
+        current_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value()));
     __ movl(out, Address(out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex())));
 
     SlowPathCodeX86* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathX86(
@@ -4338,6 +4353,7 @@
 void LocationsBuilderX86::VisitLoadString(HLoadString* load) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kCallOnSlowPath);
+  locations->SetInAt(0, Location::RequiresRegister());
   locations->SetOut(Location::RequiresRegister());
 }
 
@@ -4345,9 +4361,10 @@
   SlowPathCodeX86* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathX86(load);
   codegen_->AddSlowPath(slow_path);
 
-  Register out = load->GetLocations()->Out().AsRegister<Register>();
-  codegen_->LoadCurrentMethod(out);
-  __ movl(out, Address(out, mirror::ArtMethod::DeclaringClassOffset().Int32Value()));
+  LocationSummary* locations = load->GetLocations();
+  Register out = locations->Out().AsRegister<Register>();
+  Register current_method = locations->InAt(0).AsRegister<Register>();
+  __ 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 f49c26d..78d5851 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"
@@ -39,13 +39,13 @@
 static constexpr Register TMP = R11;
 
 static constexpr int kCurrentMethodStackOffset = 0;
+static constexpr Register kMethodRegisterArgument = RDI;
 
 static constexpr Register kCoreCalleeSaves[] = { RBX, RBP, R12, R13, R14, R15 };
 static constexpr FloatRegister kFpuCalleeSaves[] = { XMM12, XMM13, XMM14, XMM15 };
 
 static constexpr int kC2ConditionMask = 0x400;
 
-
 #define __ reinterpret_cast<X86_64Assembler*>(codegen->GetAssembler())->
 
 class NullCheckSlowPathX86_64 : public SlowPathCodeX86_64 {
@@ -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,8 @@
     }
   }
 
-  __ movl(Address(CpuRegister(RSP), kCurrentMethodStackOffset), CpuRegister(RDI));
+  __ movq(Address(CpuRegister(RSP), kCurrentMethodStackOffset),
+          CpuRegister(kMethodRegisterArgument));
 }
 
 void CodeGeneratorX86_64::GenerateFrameExit() {
@@ -585,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 {
@@ -689,11 +691,11 @@
                                Location location,
                                HInstruction* move_for) {
   LocationSummary* locations = instruction->GetLocations();
-  if (locations != nullptr && locations->Out().Equals(location)) {
+  if (instruction->IsCurrentMethod()) {
+    Move(location, Location::DoubleStackSlot(kCurrentMethodStackOffset));
+  } else if (locations != nullptr && locations->Out().Equals(location)) {
     return;
-  }
-
-  if (locations != nullptr && locations->Out().IsConstant()) {
+  } else if (locations != nullptr && locations->Out().IsConstant()) {
     HConstant* const_to_move = locations->Out().GetConstant();
     if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) {
       Immediate imm(GetInt32ValueOf(const_to_move));
@@ -944,19 +946,19 @@
   UNUSED(store);
 }
 
-void LocationsBuilderX86_64::VisitCondition(HCondition* comp) {
+void LocationsBuilderX86_64::VisitCondition(HCondition* cond) {
   LocationSummary* locations =
-      new (GetGraph()->GetArena()) LocationSummary(comp, LocationSummary::kNoCall);
+      new (GetGraph()->GetArena()) LocationSummary(cond, LocationSummary::kNoCall);
   locations->SetInAt(0, Location::RequiresRegister());
   locations->SetInAt(1, Location::Any());
-  if (comp->NeedsMaterialization()) {
+  if (cond->NeedsMaterialization()) {
     locations->SetOut(Location::RequiresRegister());
   }
 }
 
-void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* comp) {
-  if (comp->NeedsMaterialization()) {
-    LocationSummary* locations = comp->GetLocations();
+void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* cond) {
+  if (cond->NeedsMaterialization()) {
+    LocationSummary* locations = cond->GetLocations();
     CpuRegister reg = locations->Out().AsRegister<CpuRegister>();
     // Clear register: setcc only sets the low byte.
     __ xorl(reg, reg);
@@ -974,7 +976,7 @@
     } else {
       __ cmpl(lhs.AsRegister<CpuRegister>(), Address(CpuRegister(RSP), rhs.GetStackIndex()));
     }
-    __ setcc(X86_64Condition(comp->GetCondition()), reg);
+    __ setcc(X86_64Condition(cond->GetCondition()), reg);
   }
 }
 
@@ -1339,7 +1341,7 @@
 void LocationsBuilderX86_64::HandleInvoke(HInvoke* invoke) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(invoke, LocationSummary::kCall);
-  locations->AddTemp(Location::RegisterLocation(RDI));
+  locations->AddTemp(Location::RegisterLocation(kMethodRegisterArgument));
 
   InvokeDexCallingConventionVisitorX86_64 calling_convention_visitor;
   for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) {
@@ -1383,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();
@@ -1397,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());
@@ -1415,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();
@@ -1434,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());
@@ -2117,6 +2119,8 @@
       if (second.IsRegister()) {
         if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
           __ addl(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
+        } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
+          __ addl(out.AsRegister<CpuRegister>(), first.AsRegister<CpuRegister>());
         } else {
           __ leal(out.AsRegister<CpuRegister>(), Address(
               first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>(), TIMES_1, 0));
@@ -2140,6 +2144,8 @@
       if (second.IsRegister()) {
         if (out.AsRegister<Register>() == first.AsRegister<Register>()) {
           __ addq(out.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>());
+        } else if (out.AsRegister<Register>() == second.AsRegister<Register>()) {
+          __ addq(out.AsRegister<CpuRegister>(), first.AsRegister<CpuRegister>());
         } else {
           __ leaq(out.AsRegister<CpuRegister>(), Address(
               first.AsRegister<CpuRegister>(), second.AsRegister<CpuRegister>(), TIMES_1, 0));
@@ -3066,9 +3072,20 @@
   locations->SetOut(location);
 }
 
-void InstructionCodeGeneratorX86_64::VisitParameterValue(HParameterValue* instruction) {
+void InstructionCodeGeneratorX86_64::VisitParameterValue(
+    HParameterValue* instruction ATTRIBUTE_UNUSED) {
   // Nothing to do, the parameter is already at its location.
-  UNUSED(instruction);
+}
+
+void LocationsBuilderX86_64::VisitCurrentMethod(HCurrentMethod* instruction) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+  locations->SetOut(Location::RegisterLocation(kMethodRegisterArgument));
+}
+
+void InstructionCodeGeneratorX86_64::VisitCurrentMethod(
+    HCurrentMethod* instruction ATTRIBUTE_UNUSED) {
+  // Nothing to do, the method is already at its location.
 }
 
 void LocationsBuilderX86_64::VisitNot(HNot* not_) {
@@ -4123,20 +4140,22 @@
       : LocationSummary::kNoCall;
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(cls, call_kind);
+  locations->SetInAt(0, Location::RequiresRegister());
   locations->SetOut(Location::RequiresRegister());
 }
 
 void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) {
-  CpuRegister out = cls->GetLocations()->Out().AsRegister<CpuRegister>();
+  LocationSummary* locations = cls->GetLocations();
+  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
+  CpuRegister current_method = locations->InAt(0).AsRegister<CpuRegister>();
   if (cls->IsReferrersClass()) {
     DCHECK(!cls->CanCallRuntime());
     DCHECK(!cls->MustGenerateClinitCheck());
-    codegen_->LoadCurrentMethod(out);
-    __ movl(out, Address(out, mirror::ArtMethod::DeclaringClassOffset().Int32Value()));
+    __ movl(out, Address(current_method, ArtMethod::DeclaringClassOffset().Int32Value()));
   } else {
     DCHECK(cls->CanCallRuntime());
-    codegen_->LoadCurrentMethod(out);
-    __ movl(out, Address(out, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value()));
+    __ movl(out, Address(
+        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());
@@ -4172,6 +4191,7 @@
 void LocationsBuilderX86_64::VisitLoadString(HLoadString* load) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(load, LocationSummary::kCallOnSlowPath);
+  locations->SetInAt(0, Location::RequiresRegister());
   locations->SetOut(Location::RequiresRegister());
 }
 
@@ -4179,9 +4199,10 @@
   SlowPathCodeX86_64* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathX86_64(load);
   codegen_->AddSlowPath(slow_path);
 
-  CpuRegister out = load->GetLocations()->Out().AsRegister<CpuRegister>();
-  codegen_->LoadCurrentMethod(CpuRegister(out));
-  __ movl(out, Address(out, mirror::ArtMethod::DeclaringClassOffset().Int32Value()));
+  LocationSummary* locations = load->GetLocations();
+  CpuRegister out = locations->Out().AsRegister<CpuRegister>();
+  CpuRegister current_method = locations->InAt(0).AsRegister<CpuRegister>();
+  __ 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/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 7da4f2d..fd2e4e8 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -280,6 +280,13 @@
         << instance_of->MustDoNullCheck() << std::noboolalpha;
   }
 
+  void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
+    StartAttributeStream("dex_file_index") << invoke->GetDexMethodIndex();
+    StartAttributeStream("recursive") << std::boolalpha
+                                      << invoke->IsRecursive()
+                                      << std::noboolalpha;
+  }
+
   bool IsPass(const char* name) {
     return strcmp(pass_name_, name) == 0;
   }
diff --git a/compiler/optimizing/gvn_test.cc b/compiler/optimizing/gvn_test.cc
index c3ce7e1..d8a09ff 100644
--- a/compiler/optimizing/gvn_test.cc
+++ b/compiler/optimizing/gvn_test.cc
@@ -40,23 +40,40 @@
   graph->AddBlock(block);
   entry->AddSuccessor(block);
 
-  block->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot,
-          MemberOffset(42), false));
-  block->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot,
-          MemberOffset(42), false));
+  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                           Primitive::kPrimNot,
+                                                           MemberOffset(42),
+                                                           false,
+                                                           kUnknownFieldIndex,
+                                                           graph->GetDexFile()));
+  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                           Primitive::kPrimNot,
+                                                           MemberOffset(42),
+                                                           false,
+                                                           kUnknownFieldIndex,
+                                                           graph->GetDexFile()));
   HInstruction* to_remove = block->GetLastInstruction();
-  block->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot,
-          MemberOffset(43), false));
+  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                           Primitive::kPrimNot,
+                                                           MemberOffset(43),
+                                                           false,
+                                                           kUnknownFieldIndex,
+                                                           graph->GetDexFile()));
   HInstruction* different_offset = block->GetLastInstruction();
   // Kill the value.
-  block->AddInstruction(new (&allocator) HInstanceFieldSet(
-      parameter, parameter, Primitive::kPrimNot, MemberOffset(42), false));
-  block->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot,
-          MemberOffset(42), false));
+  block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
+                                                           parameter,
+                                                           Primitive::kPrimNot,
+                                                           MemberOffset(42),
+                                                           false,
+                                                           kUnknownFieldIndex,
+                                                           graph->GetDexFile()));
+  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                           Primitive::kPrimNot,
+                                                           MemberOffset(42),
+                                                           false,
+                                                           kUnknownFieldIndex,
+                                                           graph->GetDexFile()));
   HInstruction* use_after_kill = block->GetLastInstruction();
   block->AddInstruction(new (&allocator) HExit());
 
@@ -88,9 +105,12 @@
   HBasicBlock* block = new (&allocator) HBasicBlock(graph);
   graph->AddBlock(block);
   entry->AddSuccessor(block);
-  block->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
-          MemberOffset(42), false));
+  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                           Primitive::kPrimBoolean,
+                                                           MemberOffset(42),
+                                                           false,
+                                                           kUnknownFieldIndex,
+                                                           graph->GetDexFile()));
 
   block->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
   HBasicBlock* then = new (&allocator) HBasicBlock(graph);
@@ -105,17 +125,26 @@
   then->AddSuccessor(join);
   else_->AddSuccessor(join);
 
-  then->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
-          MemberOffset(42), false));
+  then->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                          Primitive::kPrimBoolean,
+                                                          MemberOffset(42),
+                                                          false,
+                                                          kUnknownFieldIndex,
+                                                          graph->GetDexFile()));
   then->AddInstruction(new (&allocator) HGoto());
-  else_->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
-          MemberOffset(42), false));
+  else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                           Primitive::kPrimBoolean,
+                                                           MemberOffset(42),
+                                                           false,
+                                                           kUnknownFieldIndex,
+                                                           graph->GetDexFile()));
   else_->AddInstruction(new (&allocator) HGoto());
-  join->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
-          MemberOffset(42), false));
+  join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                          Primitive::kPrimBoolean,
+                                                          MemberOffset(42),
+                                                          false,
+                                                          kUnknownFieldIndex,
+                                                          graph->GetDexFile()));
   join->AddInstruction(new (&allocator) HExit());
 
   graph->TryBuildingSsa();
@@ -144,9 +173,12 @@
   HBasicBlock* block = new (&allocator) HBasicBlock(graph);
   graph->AddBlock(block);
   entry->AddSuccessor(block);
-  block->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
-          MemberOffset(42), false));
+  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                           Primitive::kPrimBoolean,
+                                                           MemberOffset(42),
+                                                           false,
+                                                           kUnknownFieldIndex,
+                                                           graph->GetDexFile()));
   block->AddInstruction(new (&allocator) HGoto());
 
   HBasicBlock* loop_header = new (&allocator) HBasicBlock(graph);
@@ -161,26 +193,40 @@
   loop_header->AddSuccessor(exit);
   loop_body->AddSuccessor(loop_header);
 
-  loop_header->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
-          MemberOffset(42), false));
+  loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                                 Primitive::kPrimBoolean,
+                                                                 MemberOffset(42),
+                                                                 false,
+                                                                 kUnknownFieldIndex,
+                                                                 graph->GetDexFile()));
   HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction();
   loop_header->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
 
   // Kill inside the loop body to prevent field gets inside the loop header
   // and the body to be GVN'ed.
-  loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(
-      parameter, parameter, Primitive::kPrimNot, MemberOffset(42), false));
+  loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
+                                                               parameter,
+                                                               Primitive::kPrimNot,
+                                                               MemberOffset(42),
+                                                               false,
+                                                               kUnknownFieldIndex,
+                                                               graph->GetDexFile()));
   HInstruction* field_set = loop_body->GetLastInstruction();
-  loop_body->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
-          MemberOffset(42), false));
+  loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                               Primitive::kPrimBoolean,
+                                                               MemberOffset(42),
+                                                               false,
+                                                               kUnknownFieldIndex,
+                                                               graph->GetDexFile()));
   HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction();
   loop_body->AddInstruction(new (&allocator) HGoto());
 
-  exit->AddInstruction(
-      new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean,
-          MemberOffset(42), false));
+  exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
+                                                          Primitive::kPrimBoolean,
+                                                          MemberOffset(42),
+                                                          false,
+                                                          kUnknownFieldIndex,
+                                                          graph->GetDexFile()));
   HInstruction* field_get_in_exit = exit->GetLastInstruction();
   exit->AddInstruction(new (&allocator) HExit());
 
@@ -266,8 +312,13 @@
   // Check that the loops don't have side effects.
   {
     // Make one block with a side effect.
-    entry->AddInstruction(new (&allocator) HInstanceFieldSet(
-        parameter, parameter, Primitive::kPrimNot, MemberOffset(42), false));
+    entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
+                                                             parameter,
+                                                             Primitive::kPrimNot,
+                                                             MemberOffset(42),
+                                                             false,
+                                                             kUnknownFieldIndex,
+                                                             graph->GetDexFile()));
 
     SideEffectsAnalysis side_effects(graph);
     side_effects.Run();
@@ -280,8 +331,13 @@
   // Check that the side effects of the outer loop does not affect the inner loop.
   {
     outer_loop_body->InsertInstructionBefore(
-        new (&allocator) HInstanceFieldSet(
-            parameter, parameter, Primitive::kPrimNot, MemberOffset(42), false),
+        new (&allocator) HInstanceFieldSet(parameter,
+                                           parameter,
+                                           Primitive::kPrimNot,
+                                           MemberOffset(42),
+                                           false,
+                                           kUnknownFieldIndex,
+                                           graph->GetDexFile()),
         outer_loop_body->GetLastInstruction());
 
     SideEffectsAnalysis side_effects(graph);
@@ -297,8 +353,13 @@
   {
     outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
     inner_loop_body->InsertInstructionBefore(
-        new (&allocator) HInstanceFieldSet(
-            parameter, parameter, Primitive::kPrimNot, MemberOffset(42), false),
+        new (&allocator) HInstanceFieldSet(parameter,
+                                           parameter,
+                                           Primitive::kPrimNot,
+                                           MemberOffset(42),
+                                           false,
+                                           kUnknownFieldIndex,
+                                           graph->GetDexFile()),
         inner_loop_body->GetLastInstruction());
 
     SideEffectsAnalysis side_effects(graph);
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 56d868f..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"
@@ -36,8 +36,8 @@
 
 namespace art {
 
-static constexpr int kMaxInlineCodeUnits = 100;
-static constexpr int kDepthLimit = 5;
+static constexpr int kMaxInlineCodeUnits = 18;
+static constexpr int kDepthLimit = 3;
 
 void HInliner::Run() {
   if (graph_->IsDebuggable()) {
@@ -46,8 +46,15 @@
     return;
   }
   const GrowableArray<HBasicBlock*>& blocks = graph_->GetReversePostOrder();
+  HBasicBlock* next_block = blocks.Get(0);
   for (size_t i = 0; i < blocks.Size(); ++i) {
-    HBasicBlock* block = blocks.Get(i);
+    // Because we are changing the graph when inlining, we need to remember the next block.
+    // This avoids doing the inlining work again on the inlined blocks.
+    if (blocks.Get(i) != next_block) {
+      continue;
+    }
+    HBasicBlock* block = next_block;
+    next_block = (i == blocks.Size() - 1) ? nullptr : blocks.Get(i + 1);
     for (HInstruction* instruction = block->GetFirstInstruction(); instruction != nullptr;) {
       HInstruction* next = instruction->GetNext();
       HInvokeStaticOrDirect* call = instruction->AsInvokeStaticOrDirect();
@@ -81,19 +88,18 @@
       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;
   }
 
-  bool can_use_dex_cache = true;
+  bool same_dex_file = true;
   const DexFile& outer_dex_file = *outer_compilation_unit_.GetDexFile();
   if (resolved_method->GetDexFile()->GetLocation().compare(outer_dex_file.GetLocation()) != 0) {
-    can_use_dex_cache = false;
+    same_dex_file = false;
   }
 
   const DexFile::CodeItem* code_item = resolved_method->GetCodeItem();
@@ -140,8 +146,7 @@
     return false;
   }
 
-  if (!TryBuildAndInline(resolved_method, invoke_instruction, method_index, can_use_dex_cache)) {
-    resolved_method->SetShouldNotInline();
+  if (!TryBuildAndInline(resolved_method, invoke_instruction, method_index, same_dex_file)) {
     return false;
   }
 
@@ -150,10 +155,10 @@
   return true;
 }
 
-bool HInliner::TryBuildAndInline(Handle<mirror::ArtMethod> resolved_method,
+bool HInliner::TryBuildAndInline(ArtMethod* resolved_method,
                                  HInvoke* invoke_instruction,
                                  uint32_t method_index,
-                                 bool can_use_dex_cache) const {
+                                 bool same_dex_file) const {
   ScopedObjectAccess soa(Thread::Current());
   const DexFile::CodeItem* code_item = resolved_method->GetCodeItem();
   const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
@@ -193,6 +198,8 @@
       caller_dex_file,
       method_index,
       requires_ctor_barrier,
+      compiler_driver_->GetInstructionSet(),
+      invoke_instruction->GetOriginalInvokeType(),
       graph_->IsDebuggable(),
       graph_->GetCurrentInstructionId());
 
@@ -207,6 +214,9 @@
   if (!builder.BuildGraph(*code_item)) {
     VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
                    << " could not be built, so cannot be inlined";
+    // There could be multiple reasons why the graph could not be built, including
+    // unaccessible methods/fields due to using a different dex cache. We do not mark
+    // the method as non-inlineable so that other callers can still try to inline it.
     return false;
   }
 
@@ -214,12 +224,14 @@
                                                   compiler_driver_->GetInstructionSet())) {
     VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
                    << " cannot be inlined because of the register allocator";
+    resolved_method->SetShouldNotInline();
     return false;
   }
 
   if (!callee_graph->TryBuildingSsa()) {
     VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
                    << " could not be transformed to SSA";
+    resolved_method->SetShouldNotInline();
     return false;
   }
 
@@ -249,6 +261,31 @@
     inliner.Run();
   }
 
+  // TODO: We should abort only if all predecessors throw. However,
+  // HGraph::InlineInto currently does not handle an exit block with
+  // a throw predecessor.
+  HBasicBlock* exit_block = callee_graph->GetExitBlock();
+  if (exit_block == nullptr) {
+    VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
+                   << " could not be inlined because it has an infinite loop";
+    resolved_method->SetShouldNotInline();
+    return false;
+  }
+
+  bool has_throw_predecessor = false;
+  for (size_t i = 0, e = exit_block->GetPredecessors().Size(); i < e; ++i) {
+    if (exit_block->GetPredecessors().Get(i)->GetLastInstruction()->IsThrow()) {
+      has_throw_predecessor = true;
+      break;
+    }
+  }
+  if (has_throw_predecessor) {
+    VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
+                   << " could not be inlined because one branch always throws";
+    resolved_method->SetShouldNotInline();
+    return false;
+  }
+
   HReversePostOrderIterator it(*callee_graph);
   it.Advance();  // Past the entry block, it does not contain instructions that prevent inlining.
   for (; !it.Done(); it.Advance()) {
@@ -256,6 +293,7 @@
     if (block->IsLoopHeader()) {
       VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
                      << " could not be inlined because it contains a loop";
+      resolved_method->SetShouldNotInline();
       return false;
     }
 
@@ -263,28 +301,29 @@
          !instr_it.Done();
          instr_it.Advance()) {
       HInstruction* current = instr_it.Current();
-      if (current->IsSuspendCheck()) {
-        continue;
-      }
 
-      if (current->CanThrow()) {
+      if (current->IsInvokeInterface()) {
+        // Disable inlining of interface calls. The cost in case of entering the
+        // resolution conflict is currently too high.
         VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
-                       << " could not be inlined because " << current->DebugName()
-                       << " can throw";
+                       << " could not be inlined because it has an interface call.";
+        resolved_method->SetShouldNotInline();
         return false;
       }
 
-      if (current->NeedsEnvironment()) {
+      if (!same_dex_file && current->NeedsEnvironment()) {
         VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
                        << " could not be inlined because " << current->DebugName()
-                       << " needs an environment";
+                       << " needs an environment and is in a different dex file";
         return false;
       }
 
-      if (!can_use_dex_cache && current->NeedsDexCache()) {
+      if (!same_dex_file && current->NeedsDexCache()) {
         VLOG(compiler) << "Method " << PrettyMethod(method_index, caller_dex_file)
                        << " could not be inlined because " << current->DebugName()
                        << " it is in a different dex file and requires access to the dex cache";
+        // Do not flag the method as not-inlineable. A caller within the same
+        // dex file could still successfully inline it.
         return false;
       }
     }
@@ -292,10 +331,6 @@
 
   callee_graph->InlineInto(graph_, invoke_instruction);
 
-  if (callee_graph->HasBoundsChecks()) {
-    graph_->SetHasBoundsChecks(true);
-  }
-
   return true;
 }
 
diff --git a/compiler/optimizing/inliner.h b/compiler/optimizing/inliner.h
index 1dbc7d3..b86c1ed 100644
--- a/compiler/optimizing/inliner.h
+++ b/compiler/optimizing/inliner.h
@@ -48,10 +48,10 @@
 
  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 can_use_dex_cache) const;
+                         bool same_dex_file) const;
 
   const DexCompilationUnit& outer_compilation_unit_;
   const DexCompilationUnit& caller_compilation_unit_;
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 43fe374..8ef13e1 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -22,6 +22,7 @@
 #include "invoke_type.h"
 #include "nodes.h"
 #include "quick/inline_method_analyser.h"
+#include "utils.h"
 
 namespace art {
 
@@ -326,9 +327,6 @@
 
 // TODO: Refactor DexFileMethodInliner and have something nicer than InlineMethod.
 void IntrinsicsRecognizer::Run() {
-  DexFileMethodInliner* inliner = driver_->GetMethodInlinerMap()->GetMethodInliner(dex_file_);
-  DCHECK(inliner != nullptr);
-
   for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
     HBasicBlock* block = it.Current();
     for (HInstructionIterator inst_it(block->GetInstructions()); !inst_it.Done();
@@ -337,6 +335,9 @@
       if (inst->IsInvoke()) {
         HInvoke* invoke = inst->AsInvoke();
         InlineMethod method;
+        DexFileMethodInliner* inliner =
+            driver_->GetMethodInlinerMap()->GetMethodInliner(&invoke->GetDexFile());
+        DCHECK(inliner != nullptr);
         if (inliner->IsIntrinsic(invoke->GetDexMethodIndex(), &method)) {
           Intrinsics intrinsic = GetIntrinsic(method);
 
@@ -344,7 +345,7 @@
             if (!CheckInvokeType(intrinsic, invoke)) {
               LOG(WARNING) << "Found an intrinsic with unexpected invoke type: "
                            << intrinsic << " for "
-                           << PrettyMethod(invoke->GetDexMethodIndex(), *dex_file_);
+                           << PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile());
             } else {
               invoke->SetIntrinsic(intrinsic);
             }
diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h
index c243ef3..741fb64 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -30,16 +30,15 @@
 // Recognize intrinsics from HInvoke nodes.
 class IntrinsicsRecognizer : public HOptimization {
  public:
-  IntrinsicsRecognizer(HGraph* graph, const DexFile* dex_file, CompilerDriver* driver)
+  IntrinsicsRecognizer(HGraph* graph, CompilerDriver* driver)
       : HOptimization(graph, true, kIntrinsicsRecognizerPassName),
-        dex_file_(dex_file), driver_(driver) {}
+        driver_(driver) {}
 
   void Run() OVERRIDE;
 
   static constexpr const char* kIntrinsicsRecognizerPassName = "intrinsics_recognition";
 
  private:
-  const DexFile* dex_file_;
   CompilerDriver* driver_;
 
   DISALLOW_COPY_AND_ASSIGN(IntrinsicsRecognizer);
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 47da9cc..cd91d2c 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -19,6 +19,7 @@
 #include "code_generator.h"
 #include "ssa_builder.h"
 #include "base/bit_vector-inl.h"
+#include "base/bit_utils.h"
 #include "utils/growable_array.h"
 #include "scoped_thread_state_change.h"
 
@@ -294,6 +295,20 @@
   return cached_null_constant_;
 }
 
+HCurrentMethod* HGraph::GetCurrentMethod() {
+  if (cached_current_method_ == nullptr) {
+    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 {
+      entry_block_->InsertInstructionBefore(
+          cached_current_method_, entry_block_->GetFirstInstruction());
+    }
+  }
+  return cached_current_method_;
+}
+
 HConstant* HGraph::GetConstant(Primitive::Type type, int64_t value) {
   switch (type) {
     case Primitive::Type::kPrimBoolean:
@@ -1290,11 +1305,39 @@
     block->RemovePhi(it.Current()->AsPhi());
   }
 
+  if (block->IsExitBlock()) {
+    exit_block_ = nullptr;
+  }
+
   reverse_post_order_.Delete(block);
   blocks_.Put(block->GetBlockId(), nullptr);
 }
 
 void HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) {
+  DCHECK(HasExitBlock()) << "Unimplemented scenario";
+  // Update the environments in this graph to have the invoke's environment
+  // as parent.
+  {
+    HReversePostOrderIterator it(*this);
+    it.Advance();  // Skip the entry block, we do not need to update the entry's suspend check.
+    for (; !it.Done(); it.Advance()) {
+      HBasicBlock* block = it.Current();
+      for (HInstructionIterator instr_it(block->GetInstructions());
+           !instr_it.Done();
+           instr_it.Advance()) {
+        HInstruction* current = instr_it.Current();
+        if (current->NeedsEnvironment()) {
+          current->GetEnvironment()->SetAndCopyParentChain(
+              outer_graph->GetArena(), invoke->GetEnvironment());
+        }
+      }
+    }
+  }
+  outer_graph->UpdateMaximumNumberOfOutVRegs(GetMaximumNumberOfOutVRegs());
+  if (HasBoundsChecks()) {
+    outer_graph->SetHasBoundsChecks(true);
+  }
+
   if (GetBlocks().Size() == 3) {
     // Simple case of an entry block, a body block, and an exit block.
     // Put the body block's instruction into `invoke`'s block.
@@ -1455,6 +1498,8 @@
         DCHECK(parameter_index != last_input_index);
       }
       current->ReplaceWith(invoke->InputAt(parameter_index++));
+    } else if (current->IsCurrentMethod()) {
+      current->ReplaceWith(outer_graph->GetCurrentMethod());
     } else {
       DCHECK(current->IsGoto() || current->IsSuspendCheck());
       entry_block_->RemoveInstruction(current);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index b712e5e..6c8098b 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -35,6 +35,7 @@
 
 class GraphChecker;
 class HBasicBlock;
+class HCurrentMethod;
 class HDoubleConstant;
 class HEnvironment;
 class HFloatConstant;
@@ -60,6 +61,10 @@
 static constexpr uint32_t kMaxIntShiftValue = 0x1f;
 static constexpr uint64_t kMaxLongShiftValue = 0x3f;
 
+static constexpr uint32_t kUnknownFieldIndex = static_cast<uint32_t>(-1);
+
+static constexpr InvokeType kInvalidInvokeType = static_cast<InvokeType>(-1);
+
 enum IfCondition {
   kCondEQ,
   kCondNE,
@@ -121,6 +126,8 @@
          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)
       : arena_(arena),
@@ -138,12 +145,16 @@
         current_instruction_id_(start_instruction_id),
         dex_file_(dex_file),
         method_idx_(method_idx),
+        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()),
         cached_long_constants_(std::less<int64_t>(), arena->Adapter()),
-        cached_double_constants_(std::less<int64_t>(), arena->Adapter()) {}
+        cached_double_constants_(std::less<int64_t>(), arena->Adapter()),
+        cached_current_method_(nullptr) {}
 
   ArenaAllocator* GetArena() const { return arena_; }
   const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
@@ -151,6 +162,7 @@
 
   HBasicBlock* GetEntryBlock() const { return entry_block_; }
   HBasicBlock* GetExitBlock() const { return exit_block_; }
+  bool HasExitBlock() const { return exit_block_ != nullptr; }
 
   void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
   void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
@@ -167,6 +179,7 @@
     // users remaining when being visited.
     if (!AnalyzeNaturalLoops()) return false;
     TransformToSsa();
+    in_ssa_form_ = true;
     return true;
   }
 
@@ -209,11 +222,16 @@
     maximum_number_of_out_vregs_ = new_value;
   }
 
+  void UpdateMaximumNumberOfOutVRegs(uint16_t other_value) {
+    maximum_number_of_out_vregs_ = std::max(maximum_number_of_out_vregs_, other_value);
+  }
+
   void UpdateTemporariesVRegSlots(size_t slots) {
     temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
   }
 
   size_t GetTemporariesVRegSlots() const {
+    DCHECK(!in_ssa_form_);
     return temporaries_vreg_slots_;
   }
 
@@ -222,6 +240,7 @@
   }
 
   uint16_t GetNumberOfVRegs() const {
+    DCHECK(!in_ssa_form_);
     return number_of_vregs_;
   }
 
@@ -230,6 +249,7 @@
   }
 
   uint16_t GetNumberOfLocalVRegs() const {
+    DCHECK(!in_ssa_form_);
     return number_of_vregs_ - number_of_in_vregs_;
   }
 
@@ -273,6 +293,8 @@
     return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_);
   }
 
+  HCurrentMethod* GetCurrentMethod();
+
   HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
 
   const DexFile& GetDexFile() const {
@@ -283,6 +305,10 @@
     return method_idx_;
   }
 
+  InvokeType GetInvokeType() const {
+    return invoke_type_;
+  }
+
  private:
   void VisitBlockForDominatorTree(HBasicBlock* block,
                                   HBasicBlock* predecessor,
@@ -365,8 +391,18 @@
   // The method index in the dex file.
   const uint32_t method_idx_;
 
+  // If inlined, this encodes how the callee is being invoked.
+  const InvokeType invoke_type_;
+
+  // Whether the graph has been transformed to SSA form. Only used
+  // in debug mode to ensure we are not using properties only valid
+  // for non-SSA form (like the number of temporaries).
+  bool in_ssa_form_;
+
   const bool should_generate_constructor_barrier_;
 
+  const InstructionSet instruction_set_;
+
   // Cached constants.
   HNullConstant* cached_null_constant_;
   ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
@@ -374,6 +410,8 @@
   ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_;
   ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_;
 
+  HCurrentMethod* cached_current_method_;
+
   friend class SsaBuilder;           // For caching constants.
   friend class SsaLivenessAnalysis;  // For the linear order.
   ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
@@ -799,6 +837,7 @@
   M(ClinitCheck, Instruction)                                           \
   M(Compare, BinaryOperation)                                           \
   M(Condition, BinaryOperation)                                         \
+  M(CurrentMethod, Instruction)                                         \
   M(Deoptimize, Instruction)                                            \
   M(Div, BinaryOperation)                                               \
   M(DivZeroCheck, Instruction)                                          \
@@ -1101,13 +1140,17 @@
                size_t number_of_vregs,
                const DexFile& dex_file,
                uint32_t method_idx,
-               uint32_t dex_pc)
+               uint32_t dex_pc,
+               InvokeType invoke_type,
+               HInstruction* holder)
      : vregs_(arena, number_of_vregs),
        locations_(arena, number_of_vregs),
        parent_(nullptr),
        dex_file_(dex_file),
        method_idx_(method_idx),
-       dex_pc_(dex_pc) {
+       dex_pc_(dex_pc),
+       invoke_type_(invoke_type),
+       holder_(holder) {
     vregs_.SetSize(number_of_vregs);
     for (size_t i = 0; i < number_of_vregs; i++) {
       vregs_.Put(i, HUserRecord<HEnvironment*>());
@@ -1119,16 +1162,25 @@
     }
   }
 
+  HEnvironment(ArenaAllocator* arena, const HEnvironment& to_copy, HInstruction* holder)
+      : HEnvironment(arena,
+                     to_copy.Size(),
+                     to_copy.GetDexFile(),
+                     to_copy.GetMethodIdx(),
+                     to_copy.GetDexPc(),
+                     to_copy.GetInvokeType(),
+                     holder) {}
+
   void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) {
-    parent_ = new (allocator) HEnvironment(allocator,
-                                           parent->Size(),
-                                           parent->GetDexFile(),
-                                           parent->GetMethodIdx(),
-                                           parent->GetDexPc());
-    if (parent->GetParent() != nullptr) {
-      parent_->SetAndCopyParentChain(allocator, parent->GetParent());
+    if (parent_ != nullptr) {
+      parent_->SetAndCopyParentChain(allocator, parent);
+    } else {
+      parent_ = new (allocator) HEnvironment(allocator, *parent, holder_);
+      parent_->CopyFrom(parent);
+      if (parent->GetParent() != nullptr) {
+        parent_->SetAndCopyParentChain(allocator, parent->GetParent());
+      }
     }
-    parent_->CopyFrom(parent);
   }
 
   void CopyFrom(const GrowableArray<HInstruction*>& locals);
@@ -1169,10 +1221,18 @@
     return method_idx_;
   }
 
+  InvokeType GetInvokeType() const {
+    return invoke_type_;
+  }
+
   const DexFile& GetDexFile() const {
     return dex_file_;
   }
 
+  HInstruction* GetHolder() const {
+    return holder_;
+  }
+
  private:
   // Record instructions' use entries of this environment for constant-time removal.
   // It should only be called by HInstruction when a new environment use is added.
@@ -1188,6 +1248,11 @@
   const DexFile& dex_file_;
   const uint32_t method_idx_;
   const uint32_t dex_pc_;
+  const InvokeType invoke_type_;
+
+  // The instruction that holds this environment. Only used in debug mode
+  // to ensure the graph is consistent.
+  HInstruction* const holder_;
 
   friend class HInstruction;
 
@@ -1395,18 +1460,18 @@
   HEnvironment* GetEnvironment() const { return environment_; }
   // Set the `environment_` field. Raw because this method does not
   // update the uses lists.
-  void SetRawEnvironment(HEnvironment* environment) { environment_ = environment; }
+  void SetRawEnvironment(HEnvironment* environment) {
+    DCHECK(environment_ == nullptr);
+    DCHECK_EQ(environment->GetHolder(), this);
+    environment_ = environment;
+  }
 
   // Set the environment of this instruction, copying it from `environment`. While
   // copying, the uses lists are being updated.
   void CopyEnvironmentFrom(HEnvironment* environment) {
+    DCHECK(environment_ == nullptr);
     ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
-    environment_ = new (allocator) HEnvironment(
-        allocator,
-        environment->Size(),
-        environment->GetDexFile(),
-        environment->GetMethodIdx(),
-        environment->GetDexPc());
+    environment_ = new (allocator) HEnvironment(allocator, *environment, this);
     environment_->CopyFrom(environment);
     if (environment->GetParent() != nullptr) {
       environment_->SetAndCopyParentChain(allocator, environment->GetParent());
@@ -1415,17 +1480,13 @@
 
   void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment,
                                                 HBasicBlock* block) {
+    DCHECK(environment_ == nullptr);
     ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
-    environment_ = new (allocator) HEnvironment(
-        allocator,
-        environment->Size(),
-        environment->GetDexFile(),
-        environment->GetMethodIdx(),
-        environment->GetDexPc());
+    environment_ = new (allocator) HEnvironment(allocator, *environment, this);
+    environment_->CopyFromWithLoopPhiAdjustment(environment, block);
     if (environment->GetParent() != nullptr) {
       environment_->SetAndCopyParentChain(allocator, environment->GetParent());
     }
-    environment_->CopyFromWithLoopPhiAdjustment(environment, block);
   }
 
   // Returns the number of entries in the environment. Typically, that is the
@@ -1811,6 +1872,19 @@
   DISALLOW_COPY_AND_ASSIGN(HDeoptimize);
 };
 
+// Represents the ArtMethod that was passed as a first argument to
+// the method. It is used by instructions that depend on it, like
+// instructions that work with the dex cache.
+class HCurrentMethod : public HExpression<0> {
+ public:
+  explicit HCurrentMethod(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
+
+  DECLARE_INSTRUCTION(CurrentMethod);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HCurrentMethod);
+};
+
 class HUnaryOperation : public HExpression<1> {
  public:
   HUnaryOperation(Primitive::Type result_type, HInstruction* input)
@@ -2375,6 +2449,9 @@
   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
 
   uint32_t GetDexMethodIndex() const { return dex_method_index_; }
+  const DexFile& GetDexFile() const { return GetEnvironment()->GetDexFile(); }
+
+  InvokeType GetOriginalInvokeType() const { return original_invoke_type_; }
 
   Intrinsics GetIntrinsic() const {
     return intrinsic_;
@@ -2384,6 +2461,12 @@
     intrinsic_ = intrinsic;
   }
 
+  bool IsInlined() const {
+    return GetEnvironment()->GetParent() != nullptr;
+  }
+
+  bool CanThrow() const OVERRIDE { return true; }
+
   DECLARE_INSTRUCTION(Invoke);
 
  protected:
@@ -2392,13 +2475,15 @@
           uint32_t number_of_other_inputs,
           Primitive::Type return_type,
           uint32_t dex_pc,
-          uint32_t dex_method_index)
+          uint32_t dex_method_index,
+          InvokeType original_invoke_type)
     : HInstruction(SideEffects::All()),
       number_of_arguments_(number_of_arguments),
       inputs_(arena, number_of_arguments),
       return_type_(return_type),
       dex_pc_(dex_pc),
       dex_method_index_(dex_method_index),
+      original_invoke_type_(original_invoke_type),
       intrinsic_(Intrinsics::kNone) {
     uint32_t number_of_inputs = number_of_arguments + number_of_other_inputs;
     inputs_.SetSize(number_of_inputs);
@@ -2414,6 +2499,7 @@
   const Primitive::Type return_type_;
   const uint32_t dex_pc_;
   const uint32_t dex_method_index_;
+  const InvokeType original_invoke_type_;
   Intrinsics intrinsic_;
 
  private:
@@ -2445,8 +2531,8 @@
                 clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u,
                 return_type,
                 dex_pc,
-                dex_method_index),
-        original_invoke_type_(original_invoke_type),
+                dex_method_index,
+                original_invoke_type),
         invoke_type_(invoke_type),
         is_recursive_(is_recursive),
         clinit_check_requirement_(clinit_check_requirement),
@@ -2459,7 +2545,6 @@
     return false;
   }
 
-  InvokeType GetOriginalInvokeType() const { return original_invoke_type_; }
   InvokeType GetInvokeType() const { return invoke_type_; }
   bool IsRecursive() const { return is_recursive_; }
   bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); }
@@ -2517,7 +2602,6 @@
   }
 
  private:
-  const InvokeType original_invoke_type_;
   const InvokeType invoke_type_;
   const bool is_recursive_;
   ClinitCheckRequirement clinit_check_requirement_;
@@ -2536,7 +2620,7 @@
                  uint32_t dex_pc,
                  uint32_t dex_method_index,
                  uint32_t vtable_index)
-      : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index),
+      : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index, kVirtual),
         vtable_index_(vtable_index) {}
 
   bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
@@ -2562,7 +2646,7 @@
                    uint32_t dex_pc,
                    uint32_t dex_method_index,
                    uint32_t imt_index)
-      : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index),
+      : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index, kInterface),
         imt_index_(imt_index) {}
 
   bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
@@ -2583,14 +2667,19 @@
 
 class HNewInstance : public HExpression<0> {
  public:
-  HNewInstance(uint32_t dex_pc, uint16_t type_index, QuickEntrypointEnum entrypoint)
+  HNewInstance(uint32_t dex_pc,
+               uint16_t type_index,
+               const DexFile& dex_file,
+               QuickEntrypointEnum entrypoint)
       : HExpression(Primitive::kPrimNot, SideEffects::None()),
         dex_pc_(dex_pc),
         type_index_(type_index),
+        dex_file_(dex_file),
         entrypoint_(entrypoint) {}
 
   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
   uint16_t GetTypeIndex() const { return type_index_; }
+  const DexFile& GetDexFile() const { return dex_file_; }
 
   // Calls runtime so needs an environment.
   bool NeedsEnvironment() const OVERRIDE { return true; }
@@ -2609,6 +2698,7 @@
  private:
   const uint32_t dex_pc_;
   const uint16_t type_index_;
+  const DexFile& dex_file_;
   const QuickEntrypointEnum entrypoint_;
 
   DISALLOW_COPY_AND_ASSIGN(HNewInstance);
@@ -2633,16 +2723,19 @@
   HNewArray(HInstruction* length,
             uint32_t dex_pc,
             uint16_t type_index,
+            const DexFile& dex_file,
             QuickEntrypointEnum entrypoint)
       : HExpression(Primitive::kPrimNot, SideEffects::None()),
         dex_pc_(dex_pc),
         type_index_(type_index),
+        dex_file_(dex_file),
         entrypoint_(entrypoint) {
     SetRawInputAt(0, length);
   }
 
   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
   uint16_t GetTypeIndex() const { return type_index_; }
+  const DexFile& GetDexFile() const { return dex_file_; }
 
   // Calls runtime so needs an environment.
   bool NeedsEnvironment() const OVERRIDE { return true; }
@@ -2659,6 +2752,7 @@
  private:
   const uint32_t dex_pc_;
   const uint16_t type_index_;
+  const DexFile& dex_file_;
   const QuickEntrypointEnum entrypoint_;
 
   DISALLOW_COPY_AND_ASSIGN(HNewArray);
@@ -3113,17 +3207,29 @@
 
 class FieldInfo : public ValueObject {
  public:
-  FieldInfo(MemberOffset field_offset, Primitive::Type field_type, bool is_volatile)
-      : field_offset_(field_offset), field_type_(field_type), is_volatile_(is_volatile) {}
+  FieldInfo(MemberOffset field_offset,
+            Primitive::Type field_type,
+            bool is_volatile,
+            uint32_t index,
+            const DexFile& dex_file)
+      : field_offset_(field_offset),
+        field_type_(field_type),
+        is_volatile_(is_volatile),
+        index_(index),
+        dex_file_(dex_file) {}
 
   MemberOffset GetFieldOffset() const { return field_offset_; }
   Primitive::Type GetFieldType() const { return field_type_; }
+  uint32_t GetFieldIndex() const { return index_; }
+  const DexFile& GetDexFile() const { return dex_file_; }
   bool IsVolatile() const { return is_volatile_; }
 
  private:
   const MemberOffset field_offset_;
   const Primitive::Type field_type_;
   const bool is_volatile_;
+  uint32_t index_;
+  const DexFile& dex_file_;
 };
 
 class HInstanceFieldGet : public HExpression<1> {
@@ -3131,9 +3237,11 @@
   HInstanceFieldGet(HInstruction* value,
                     Primitive::Type field_type,
                     MemberOffset field_offset,
-                    bool is_volatile)
+                    bool is_volatile,
+                    uint32_t field_idx,
+                    const DexFile& dex_file)
       : HExpression(field_type, SideEffects::DependsOnSomething()),
-        field_info_(field_offset, field_type, is_volatile) {
+        field_info_(field_offset, field_type, is_volatile, field_idx, dex_file) {
     SetRawInputAt(0, value);
   }
 
@@ -3171,9 +3279,11 @@
                     HInstruction* value,
                     Primitive::Type field_type,
                     MemberOffset field_offset,
-                    bool is_volatile)
+                    bool is_volatile,
+                    uint32_t field_idx,
+                    const DexFile& dex_file)
       : HTemplateInstruction(SideEffects::ChangesSomething()),
-        field_info_(field_offset, field_type, is_volatile),
+        field_info_(field_offset, field_type, is_volatile, field_idx, dex_file),
         value_can_be_null_(true) {
     SetRawInputAt(0, object);
     SetRawInputAt(1, value);
@@ -3410,17 +3520,22 @@
 /**
  * Instruction to load a Class object.
  */
-class HLoadClass : public HExpression<0> {
+class HLoadClass : public HExpression<1> {
  public:
-  HLoadClass(uint16_t type_index,
+  HLoadClass(HCurrentMethod* current_method,
+             uint16_t type_index,
+             const DexFile& dex_file,
              bool is_referrers_class,
              uint32_t dex_pc)
       : HExpression(Primitive::kPrimNot, SideEffects::None()),
         type_index_(type_index),
+        dex_file_(dex_file),
         is_referrers_class_(is_referrers_class),
         dex_pc_(dex_pc),
         generate_clinit_check_(false),
-        loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {}
+        loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {
+    SetRawInputAt(0, current_method);
+  }
 
   bool CanBeMoved() const OVERRIDE { return true; }
 
@@ -3472,12 +3587,15 @@
     return loaded_class_rti_.IsExact();
   }
 
+  const DexFile& GetDexFile() { return dex_file_; }
+
   bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; }
 
   DECLARE_INSTRUCTION(LoadClass);
 
  private:
   const uint16_t type_index_;
+  const DexFile& dex_file_;
   const bool is_referrers_class_;
   const uint32_t dex_pc_;
   // Whether this instruction must generate the initialization check.
@@ -3489,12 +3607,14 @@
   DISALLOW_COPY_AND_ASSIGN(HLoadClass);
 };
 
-class HLoadString : public HExpression<0> {
+class HLoadString : public HExpression<1> {
  public:
-  HLoadString(uint32_t string_index, uint32_t dex_pc)
+  HLoadString(HCurrentMethod* current_method, uint32_t string_index, uint32_t dex_pc)
       : HExpression(Primitive::kPrimNot, SideEffects::None()),
         string_index_(string_index),
-        dex_pc_(dex_pc) {}
+        dex_pc_(dex_pc) {
+    SetRawInputAt(0, current_method);
+  }
 
   bool CanBeMoved() const OVERRIDE { return true; }
 
@@ -3559,9 +3679,11 @@
   HStaticFieldGet(HInstruction* cls,
                   Primitive::Type field_type,
                   MemberOffset field_offset,
-                  bool is_volatile)
+                  bool is_volatile,
+                  uint32_t field_idx,
+                  const DexFile& dex_file)
       : HExpression(field_type, SideEffects::DependsOnSomething()),
-        field_info_(field_offset, field_type, is_volatile) {
+        field_info_(field_offset, field_type, is_volatile, field_idx, dex_file) {
     SetRawInputAt(0, cls);
   }
 
@@ -3596,9 +3718,11 @@
                   HInstruction* value,
                   Primitive::Type field_type,
                   MemberOffset field_offset,
-                  bool is_volatile)
+                  bool is_volatile,
+                  uint32_t field_idx,
+                  const DexFile& dex_file)
       : HTemplateInstruction(SideEffects::ChangesSomething()),
-        field_info_(field_offset, field_type, is_volatile),
+        field_info_(field_offset, field_type, is_volatile, field_idx, dex_file),
         value_can_be_null_(true) {
     SetRawInputAt(0, cls);
     SetRawInputAt(1, value);
diff --git a/compiler/optimizing/nodes_test.cc b/compiler/optimizing/nodes_test.cc
index 2736453..fef77aa 100644
--- a/compiler/optimizing/nodes_test.cc
+++ b/compiler/optimizing/nodes_test.cc
@@ -51,7 +51,7 @@
   exit_block->AddInstruction(new (&allocator) HExit());
 
   HEnvironment* environment = new (&allocator) HEnvironment(
-      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0);
+      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, null_check);
   null_check->SetRawEnvironment(environment);
   environment->SetRawEnvAt(0, parameter);
   parameter->AddEnvUseAt(null_check->GetEnvironment(), 0);
@@ -132,7 +132,7 @@
   ASSERT_TRUE(parameter1->GetUses().HasOnlyOneUse());
 
   HEnvironment* environment = new (&allocator) HEnvironment(
-      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0);
+      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, with_environment);
   GrowableArray<HInstruction*> array(&allocator, 1);
   array.Add(parameter1);
 
@@ -143,13 +143,13 @@
   ASSERT_TRUE(parameter1->GetEnvUses().HasOnlyOneUse());
 
   HEnvironment* parent1 = new (&allocator) HEnvironment(
-      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0);
+      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, nullptr);
   parent1->CopyFrom(array);
 
   ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u);
 
   HEnvironment* parent2 = new (&allocator) HEnvironment(
-      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0);
+      &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, nullptr);
   parent2->CopyFrom(array);
   parent1->SetAndCopyParentChain(&allocator, parent2);
 
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 2125f6e..2c2c55f 100644
--- a/compiler/optimizing/optimizing_cfi_test_expected.inc
+++ b/compiler/optimizing/optimizing_cfi_test_expected.inc
@@ -32,20 +32,20 @@
 // 0x00000012: .cfi_def_cfa_offset: 64
 
 static constexpr uint8_t expected_asm_kArm64[] = {
-    0xE0, 0x0F, 0x1C, 0xB8, 0xF3, 0xD3, 0x02, 0xA9, 0xFE, 0x1F, 0x00, 0xF9,
-    0xE8, 0xA7, 0x01, 0x6D, 0xE8, 0xA7, 0x41, 0x6D, 0xF3, 0xD3, 0x42, 0xA9,
+    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,
 };
 static constexpr uint8_t expected_cfi_kArm64[] = {
-    0x44, 0x0E, 0x40, 0x44, 0x93, 0x06, 0x94, 0x04, 0x44, 0x9E, 0x02, 0x44,
+    0x44, 0x0E, 0x40, 0x44, 0x94, 0x06, 0x95, 0x04, 0x44, 0x9E, 0x02, 0x44,
     0x05, 0x48, 0x0A, 0x05, 0x49, 0x08, 0x0A, 0x44, 0x06, 0x48, 0x06, 0x49,
-    0x44, 0xD3, 0xD4, 0x44, 0xDE, 0x44, 0x0E, 0x00, 0x44, 0x0B, 0x0E, 0x40,
+    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 x19, x20, [sp, #40]
-// 0x00000008: .cfi_offset: r19 at cfa-24
-// 0x00000008: .cfi_offset: r20 at cfa-16
+// 0x00000004: stp x20, x21, [sp, #40]
+// 0x00000008: .cfi_offset: r20 at cfa-24
+// 0x00000008: .cfi_offset: r21 at cfa-16
 // 0x00000008: str lr, [sp, #56]
 // 0x0000000c: .cfi_offset: r30 at cfa-8
 // 0x0000000c: stp d8, d9, [sp, #24]
@@ -55,9 +55,9 @@
 // 0x00000010: ldp d8, d9, [sp, #24]
 // 0x00000014: .cfi_restore_extended: r72
 // 0x00000014: .cfi_restore_extended: r73
-// 0x00000014: ldp x19, x20, [sp, #40]
-// 0x00000018: .cfi_restore: r19
+// 0x00000014: ldp x20, x21, [sp, #40]
 // 0x00000018: .cfi_restore: r20
+// 0x00000018: .cfi_restore: r21
 // 0x00000018: ldr lr, [sp, #56]
 // 0x0000001c: .cfi_restore: r30
 // 0x0000001c: add sp, sp, #0x40 (64)
@@ -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 be9a424..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())));
@@ -223,7 +223,6 @@
   CompiledMethod* CompileOptimized(HGraph* graph,
                                    CodeGenerator* codegen,
                                    CompilerDriver* driver,
-                                   const DexFile& dex_file,
                                    const DexCompilationUnit& dex_compilation_unit,
                                    PassInfoPrinter* pass_info) const;
 
@@ -316,7 +315,6 @@
 static void RunOptimizations(HGraph* graph,
                              CompilerDriver* driver,
                              OptimizingCompilerStats* stats,
-                             const DexFile& dex_file,
                              const DexCompilationUnit& dex_compilation_unit,
                              PassInfoPrinter* pass_info_printer,
                              StackHandleScopeCollection* handles) {
@@ -335,10 +333,10 @@
   GVNOptimization gvn(graph, side_effects);
   LICM licm(graph, side_effects);
   BoundsCheckElimination bce(graph);
-  ReferenceTypePropagation type_propagation(graph, dex_file, dex_compilation_unit, handles);
+  ReferenceTypePropagation type_propagation(graph, handles);
   InstructionSimplifier simplify2(graph, stats, "instruction_simplifier_after_types");
 
-  IntrinsicsRecognizer intrinsics(graph, dex_compilation_unit.GetDexFile(), driver);
+  IntrinsicsRecognizer intrinsics(graph, driver);
 
   HOptimization* optimizations[] = {
     &intrinsics,
@@ -391,12 +389,11 @@
 CompiledMethod* OptimizingCompiler::CompileOptimized(HGraph* graph,
                                                      CodeGenerator* codegen,
                                                      CompilerDriver* compiler_driver,
-                                                     const DexFile& dex_file,
                                                      const DexCompilationUnit& dex_compilation_unit,
                                                      PassInfoPrinter* pass_info_printer) const {
   StackHandleScopeCollection handles(Thread::Current());
   RunOptimizations(graph, compiler_driver, compilation_stats_.get(),
-                   dex_file, dex_compilation_unit, pass_info_printer, &handles);
+                   dex_compilation_unit, pass_info_printer, &handles);
 
   AllocateRegisters(graph, codegen, pass_info_printer);
 
@@ -404,7 +401,7 @@
   codegen->CompileOptimized(&allocator);
 
   DefaultSrcMap src_mapping_table;
-  if (compiler_driver->GetCompilerOptions().GetIncludeDebugSymbols()) {
+  if (compiler_driver->GetCompilerOptions().GetGenerateDebugInfo()) {
     codegen->BuildSourceMap(&src_mapping_table);
   }
 
@@ -441,7 +438,7 @@
   std::vector<uint8_t> mapping_table;
   codegen->BuildMappingTable(&mapping_table);
   DefaultSrcMap src_mapping_table;
-  if (compiler_driver->GetCompilerOptions().GetIncludeDebugSymbols()) {
+  if (compiler_driver->GetCompilerOptions().GetGenerateDebugInfo()) {
     codegen->BuildSourceMap(&src_mapping_table);
   }
   std::vector<uint8_t> vmap_table;
@@ -518,8 +515,8 @@
                                                      dex_compilation_unit.GetClassDefIndex());
   ArenaAllocator arena(Runtime::Current()->GetArenaPool());
   HGraph* graph = new (&arena) HGraph(
-      &arena, dex_file, method_idx, requires_barrier,
-      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.
@@ -537,7 +534,7 @@
     return nullptr;
   }
   codegen->GetAssembler()->cfi().SetEnabled(
-      compiler_driver->GetCompilerOptions().GetIncludeCFI());
+      compiler_driver->GetCompilerOptions().GetGenerateDebugInfo());
 
   PassInfoPrinter pass_info_printer(graph,
                                     method_name.c_str(),
@@ -585,7 +582,6 @@
     return CompileOptimized(graph,
                             codegen.get(),
                             compiler_driver,
-                            dex_file,
                             dex_compilation_unit,
                             &pass_info_printer);
   } else if (shouldOptimize && can_allocate_registers) {
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/parallel_move_resolver.h b/compiler/optimizing/parallel_move_resolver.h
index e89417d..9ede910 100644
--- a/compiler/optimizing/parallel_move_resolver.h
+++ b/compiler/optimizing/parallel_move_resolver.h
@@ -20,6 +20,7 @@
 #include "base/value_object.h"
 #include "utils/growable_array.h"
 #include "locations.h"
+#include "primitive.h"
 
 namespace art {
 
diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc
index 538736b..a249aa9 100644
--- a/compiler/optimizing/prepare_for_register_allocation.cc
+++ b/compiler/optimizing/prepare_for_register_allocation.cc
@@ -88,7 +88,11 @@
 
     // The static call will initialize the class so there's no need for a clinit check if
     // it's the first user.
-    if (last_input == invoke->GetPrevious()) {
+    // There is one special case where we still need the clinit check, when inlining. Because
+    // currently the callee is responsible for reporting parameters to the GC, the code
+    // that walks the stack during `artQuickResolutionTrampoline` cannot be interrupted for GC.
+    // Therefore we cannot allocate any object in that code, including loading a new class.
+    if (last_input == invoke->GetPrevious() && !invoke->IsInlined()) {
       last_input->SetMustGenerateClinitCheck(false);
     }
 
@@ -102,7 +106,7 @@
 
     // If the load class instruction is no longer used, remove it from
     // the graph.
-    if (!last_input->HasUses()) {
+    if (!last_input->HasUses() && !(last_input->MustGenerateClinitCheck() && invoke->IsInlined())) {
       last_input->GetBlock()->RemoveInstruction(last_input);
     }
   }
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 12b1c2b..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"
@@ -35,15 +35,22 @@
 
 void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) {
   // TODO: handle other instructions that give type info
-  // (NewArray/Call/Field accesses/array accesses)
+  // (Call/array accesses)
 
   // Initialize exact types first for faster convergence.
   for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
     HInstruction* instr = it.Current();
+    // TODO: Make ReferenceTypePropagation a visitor or create a new one.
     if (instr->IsNewInstance()) {
       VisitNewInstance(instr->AsNewInstance());
     } else if (instr->IsLoadClass()) {
       VisitLoadClass(instr->AsLoadClass());
+    } else if (instr->IsNewArray()) {
+      VisitNewArray(instr->AsNewArray());
+    } else if (instr->IsInstanceFieldGet()) {
+      VisitInstanceFieldGet(instr->AsInstanceFieldGet());
+    } else if (instr->IsStaticFieldGet()) {
+      VisitStaticFieldGet(instr->AsStaticFieldGet());
     }
   }
 
@@ -159,20 +166,61 @@
   }
 }
 
-void ReferenceTypePropagation::VisitNewInstance(HNewInstance* instr) {
-  ScopedObjectAccess soa(Thread::Current());
-  mirror::DexCache* dex_cache = dex_compilation_unit_.GetClassLinker()->FindDexCache(dex_file_);
-  // Get type from dex cache assuming it was populated by the verifier.
-  mirror::Class* resolved_class = dex_cache->GetResolvedType(instr->GetTypeIndex());
-  if (resolved_class != nullptr) {
-    MutableHandle<mirror::Class> handle = handles_->NewHandle(resolved_class);
+void ReferenceTypePropagation::SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass) {
+  if (klass != nullptr) {
+    ScopedObjectAccess soa(Thread::Current());
+    MutableHandle<mirror::Class> handle = handles_->NewHandle(klass);
     instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, true));
   }
 }
 
+void ReferenceTypePropagation::UpdateReferenceTypeInfo(HInstruction* instr,
+                                                       uint16_t type_idx,
+                                                       const DexFile& dex_file) {
+  DCHECK_EQ(instr->GetType(), Primitive::kPrimNot);
+
+  ScopedObjectAccess soa(Thread::Current());
+  mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
+  // Get type from dex cache assuming it was populated by the verifier.
+  SetClassAsTypeInfo(instr, dex_cache->GetResolvedType(type_idx));
+}
+
+void ReferenceTypePropagation::VisitNewInstance(HNewInstance* instr) {
+  UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile());
+}
+
+void ReferenceTypePropagation::VisitNewArray(HNewArray* instr) {
+  UpdateReferenceTypeInfo(instr, instr->GetTypeIndex(), instr->GetDexFile());
+}
+
+void ReferenceTypePropagation::UpdateFieldAccessTypeInfo(HInstruction* instr,
+                                                         const FieldInfo& info) {
+  // The field index is unknown only during tests.
+  if (instr->GetType() != Primitive::kPrimNot || info.GetFieldIndex() == kUnknownFieldIndex) {
+    return;
+  }
+
+  ScopedObjectAccess soa(Thread::Current());
+  ClassLinker* cl = Runtime::Current()->GetClassLinker();
+  mirror::DexCache* dex_cache = cl->FindDexCache(info.GetDexFile());
+  ArtField* field = cl->GetResolvedField(info.GetFieldIndex(), dex_cache);
+  DCHECK(field != nullptr);
+  mirror::Class* klass = field->GetType<false>();
+  SetClassAsTypeInfo(instr, klass);
+}
+
+void ReferenceTypePropagation::VisitInstanceFieldGet(HInstanceFieldGet* instr) {
+  UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
+}
+
+void ReferenceTypePropagation::VisitStaticFieldGet(HStaticFieldGet* instr) {
+  UpdateFieldAccessTypeInfo(instr, instr->GetFieldInfo());
+}
+
 void ReferenceTypePropagation::VisitLoadClass(HLoadClass* instr) {
   ScopedObjectAccess soa(Thread::Current());
-  mirror::DexCache* dex_cache = dex_compilation_unit_.GetClassLinker()->FindDexCache(dex_file_);
+  mirror::DexCache* dex_cache =
+      Runtime::Current()->GetClassLinker()->FindDexCache(instr->GetDexFile());
   // Get type from dex cache assuming it was populated by the verifier.
   mirror::Class* resolved_class = dex_cache->GetResolvedType(instr->GetTypeIndex());
   if (resolved_class != nullptr) {
diff --git a/compiler/optimizing/reference_type_propagation.h b/compiler/optimizing/reference_type_propagation.h
index 733e18e..74e425f 100644
--- a/compiler/optimizing/reference_type_propagation.h
+++ b/compiler/optimizing/reference_type_propagation.h
@@ -30,13 +30,8 @@
  */
 class ReferenceTypePropagation : public HOptimization {
  public:
-  ReferenceTypePropagation(HGraph* graph,
-                           const DexFile& dex_file,
-                           const DexCompilationUnit& dex_compilation_unit,
-                           StackHandleScopeCollection* handles)
+  ReferenceTypePropagation(HGraph* graph, StackHandleScopeCollection* handles)
     : HOptimization(graph, true, kReferenceTypePropagationPassName),
-      dex_file_(dex_file),
-      dex_compilation_unit_(dex_compilation_unit),
       handles_(handles),
       worklist_(graph->GetArena(), kDefaultWorklistSize) {}
 
@@ -47,14 +42,20 @@
  private:
   void VisitNewInstance(HNewInstance* new_instance);
   void VisitLoadClass(HLoadClass* load_class);
+  void VisitNewArray(HNewArray* instr);
   void VisitPhi(HPhi* phi);
   void VisitBasicBlock(HBasicBlock* block);
+  void UpdateFieldAccessTypeInfo(HInstruction* instr, const FieldInfo& info);
+  void SetClassAsTypeInfo(HInstruction* instr, mirror::Class* klass);
 
   void UpdateBoundType(HBoundType* bound_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void UpdatePhi(HPhi* phi) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void BoundTypeForIfNotNull(HBasicBlock* block);
   void BoundTypeForIfInstanceOf(HBasicBlock* block);
+  void UpdateReferenceTypeInfo(HInstruction* instr, uint16_t type_idx, const DexFile& dex_file);
+  void VisitInstanceFieldGet(HInstanceFieldGet* instr);
+  void VisitStaticFieldGet(HStaticFieldGet* instr);
 
   void ProcessWorklist();
   void AddToWorklist(HInstruction* instr);
@@ -66,8 +67,6 @@
   ReferenceTypeInfo MergeTypes(const ReferenceTypeInfo& a, const ReferenceTypeInfo& b)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  const DexFile& dex_file_;
-  const DexCompilationUnit& dex_compilation_unit_;
   StackHandleScopeCollection* handles_;
 
   GrowableArray<HInstruction*> worklist_;
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index 925099a..a381315 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,
@@ -482,8 +484,9 @@
       LiveInterval* current = it.CurrentInterval();
       HInstruction* defined_by = current->GetParent()->GetDefinedBy();
       if (current->GetParent()->HasSpillSlot()
-           // Parameters have their own stack slot.
-           && !(defined_by != nullptr && defined_by->IsParameterValue())) {
+           // Parameters and current method have their own stack slot.
+           && !(defined_by != nullptr && (defined_by->IsParameterValue()
+                                          || defined_by->IsCurrentMethod()))) {
         BitVector* liveness_of_spill_slot = liveness_of_values.Get(number_of_registers
             + current->GetParent()->GetSpillSlot() / kVRegSize
             - number_of_out_slots);
@@ -799,9 +802,9 @@
   current->SetRegister(reg);
   if (!current->IsDeadAt(free_until[reg])) {
     // If the register is only available for a subset of live ranges
-    // covered by `current`, split `current` at the position where
+    // covered by `current`, split `current` before the position where
     // the register is not available anymore.
-    LiveInterval* split = Split(current, free_until[reg]);
+    LiveInterval* split = SplitBetween(current, current->GetStart(), free_until[reg]);
     DCHECK(split != nullptr);
     AddSorted(unhandled_, split);
   }
@@ -1246,6 +1249,11 @@
     return;
   }
 
+  if (defined_by->IsCurrentMethod()) {
+    parent->SetSpillSlot(0);
+    return;
+  }
+
   if (defined_by->IsConstant()) {
     // Constants don't need a spill slot.
     return;
@@ -1519,7 +1527,10 @@
 
 void RegisterAllocator::ConnectSiblings(LiveInterval* interval) {
   LiveInterval* current = interval;
-  if (current->HasSpillSlot() && current->HasRegister()) {
+  if (current->HasSpillSlot()
+      && current->HasRegister()
+      // Currently, we spill unconditionnally the current method in the code generators.
+      && !interval->GetDefinedBy()->IsCurrentMethod()) {
     // We spill eagerly, so move must be at definition.
     InsertMoveAfter(interval->GetDefinedBy(),
                     interval->ToLocation(),
@@ -1574,7 +1585,7 @@
       while (env_use != nullptr && env_use->GetPosition() <= range->GetEnd()) {
         DCHECK(current->CoversSlow(env_use->GetPosition())
                || (env_use->GetPosition() == range->GetEnd()));
-        HEnvironment* environment = env_use->GetUser()->GetEnvironment();
+        HEnvironment* environment = env_use->GetEnvironment();
         environment->SetLocationAt(env_use->GetInputIndex(), source);
         env_use = env_use->GetNext();
       }
@@ -1715,6 +1726,9 @@
       } else if (current->HasSpillSlot()) {
         current->SetSpillSlot(current->GetSpillSlot() + codegen_->GetFrameSize());
       }
+    } else if (instruction->IsCurrentMethod()) {
+      // The current method is always at offset 0.
+      DCHECK(!current->HasSpillSlot() || (current->GetSpillSlot() == 0));
     } else if (current->HasSpillSlot()) {
       // Adjust the stack slot, now that we know the number of them for each type.
       // The way this implementation lays out the stack is the following:
diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h
index 6d5bfc3..c29fe75 100644
--- a/compiler/optimizing/register_allocator.h
+++ b/compiler/optimizing/register_allocator.h
@@ -17,6 +17,7 @@
 #ifndef ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_H_
 #define ART_COMPILER_OPTIMIZING_REGISTER_ALLOCATOR_H_
 
+#include "arch/instruction_set.h"
 #include "base/macros.h"
 #include "primitive.h"
 #include "utils/growable_array.h"
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index b72ffb8..d07a14a 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -474,8 +474,12 @@
   graph->AddBlock(block);
   entry->AddSuccessor(block);
 
-  HInstruction* test = new (allocator) HInstanceFieldGet(
-      parameter, Primitive::kPrimBoolean, MemberOffset(22), false);
+  HInstruction* test = new (allocator) HInstanceFieldGet(parameter,
+                                                         Primitive::kPrimBoolean,
+                                                         MemberOffset(22),
+                                                         false,
+                                                         kUnknownFieldIndex,
+                                                         graph->GetDexFile());
   block->AddInstruction(test);
   block->AddInstruction(new (allocator) HIf(test));
   HBasicBlock* then = new (allocator) HBasicBlock(graph);
@@ -494,10 +498,18 @@
 
   *phi = new (allocator) HPhi(allocator, 0, 0, Primitive::kPrimInt);
   join->AddPhi(*phi);
-  *input1 = new (allocator) HInstanceFieldGet(parameter, Primitive::kPrimInt,
-                                              MemberOffset(42), false);
-  *input2 = new (allocator) HInstanceFieldGet(parameter, Primitive::kPrimInt,
-                                              MemberOffset(42), false);
+  *input1 = new (allocator) HInstanceFieldGet(parameter,
+                                              Primitive::kPrimInt,
+                                              MemberOffset(42),
+                                              false,
+                                              kUnknownFieldIndex,
+                                              graph->GetDexFile());
+*input2 = new (allocator) HInstanceFieldGet(parameter,
+                                            Primitive::kPrimInt,
+                                            MemberOffset(42),
+                                            false,
+                                            kUnknownFieldIndex,
+                                            graph->GetDexFile());
   then->AddInstruction(*input1);
   else_->AddInstruction(*input2);
   join->AddInstruction(new (allocator) HExit());
@@ -604,8 +616,12 @@
   graph->AddBlock(block);
   entry->AddSuccessor(block);
 
-  *field = new (allocator) HInstanceFieldGet(parameter, Primitive::kPrimInt,
-                                             MemberOffset(42), false);
+  *field = new (allocator) HInstanceFieldGet(parameter,
+                                             Primitive::kPrimInt,
+                                             MemberOffset(42),
+                                             false,
+                                             kUnknownFieldIndex,
+                                             graph->GetDexFile());
   block->AddInstruction(*field);
   *ret = new (allocator) HReturn(*field);
   block->AddInstruction(*ret);
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index aac5211..c4612af 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -547,7 +547,9 @@
       current_locals_->Size(),
       GetGraph()->GetDexFile(),
       GetGraph()->GetMethodIdx(),
-      instruction->GetDexPc());
+      instruction->GetDexPc(),
+      GetGraph()->GetInvokeType(),
+      instruction);
   environment->CopyFrom(*current_locals_);
   instruction->SetRawEnvironment(environment);
 }
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 250eb04..d5f977f 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -341,6 +341,7 @@
     // starts at. If one location is a register we return it as a hint. This
     // will avoid a move between the two blocks.
     HBasicBlock* block = liveness.GetBlockFromPosition(GetStart() / 2);
+    size_t next_register_use = FirstRegisterUse();
     for (size_t i = 0; i < block->GetPredecessors().Size(); ++i) {
       size_t position = block->GetPredecessors().Get(i)->GetLifetimeEnd() - 1;
       // We know positions above GetStart() do not have a location yet.
@@ -348,7 +349,9 @@
         LiveInterval* existing = GetParent()->GetSiblingAt(position);
         if (existing != nullptr
             && existing->HasRegister()
-            && (free_until[existing->GetRegister()] > GetStart())) {
+            // It's worth using that register if it is available until
+            // the next use.
+            && (free_until[existing->GetRegister()] >= next_register_use)) {
           return existing->GetRegister();
         }
       }
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 4b19c5b..4cbe29a 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -117,6 +117,7 @@
         || user->IsPhi()
         || (GetPosition() == user->GetLifetimePosition() + 1)
         || (GetPosition() == user->GetLifetimePosition()));
+    DCHECK(environment == nullptr || user == nullptr);
     DCHECK(next_ == nullptr || next->GetPosition() >= GetPosition());
   }
 
@@ -128,6 +129,7 @@
   void SetNext(UsePosition* next) { next_ = next; }
 
   HInstruction* GetUser() const { return user_; }
+  HEnvironment* GetEnvironment() const { return environment_; }
 
   bool GetIsEnvironment() const { return environment_ != nullptr; }
   bool IsSynthesized() const { return user_ == nullptr; }
@@ -280,7 +282,7 @@
       }
       DCHECK(first_use_->GetPosition() + 1 == position);
       UsePosition* new_use = new (allocator_) UsePosition(
-          instruction, environment, input_index, position, cursor->GetNext());
+          instruction, nullptr /* environment */, input_index, position, cursor->GetNext());
       cursor->SetNext(new_use);
       if (first_range_->GetEnd() == first_use_->GetPosition()) {
         first_range_->end_ = position;
@@ -290,10 +292,10 @@
 
     if (is_environment) {
       first_env_use_ = new (allocator_) UsePosition(
-          instruction, environment, input_index, position, first_env_use_);
+          nullptr /* instruction */, environment, input_index, position, first_env_use_);
     } else {
       first_use_ = new (allocator_) UsePosition(
-          instruction, environment, input_index, position, first_use_);
+          instruction, nullptr /* environment */, input_index, position, first_use_);
     }
 
     if (is_environment && !keep_alive) {
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index 89035a3..5663e39 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -101,11 +101,13 @@
 
 void StackMapStream::BeginInlineInfoEntry(uint32_t method_index,
                                           uint32_t dex_pc,
+                                          InvokeType invoke_type,
                                           uint32_t num_dex_registers) {
   DCHECK(!in_inline_frame_);
   in_inline_frame_ = true;
   current_inline_info_.method_index = method_index;
   current_inline_info_.dex_pc = dex_pc;
+  current_inline_info_.invoke_type = invoke_type;
   current_inline_info_.num_dex_registers = num_dex_registers;
   current_inline_info_.dex_register_locations_start_index = dex_register_locations_.Size();
   if (num_dex_registers != 0) {
@@ -142,14 +144,17 @@
 
   // Note: use RoundUp to word-size here if you want CodeInfo objects to be word aligned.
   needed_size_ = CodeInfo::kFixedSize
-      + dex_register_location_catalog_size_
       + stack_maps_size_
+      + dex_register_location_catalog_size_
       + dex_register_maps_size_
       + inline_info_size_;
 
-  dex_register_location_catalog_start_ = CodeInfo::kFixedSize;
-  stack_maps_start_ = dex_register_location_catalog_start_ + dex_register_location_catalog_size_;
-  dex_register_maps_start_ = stack_maps_start_ + stack_maps_size_;
+  stack_maps_start_ = CodeInfo::kFixedSize;
+  // TODO: Move the catalog at the end. It is currently too expensive at runtime
+  // to compute its size (note that we do not encode that size in the CodeInfo).
+  dex_register_location_catalog_start_ = stack_maps_start_ + stack_maps_size_;
+  dex_register_maps_start_ =
+      dex_register_location_catalog_start_ + dex_register_location_catalog_size_;
   inline_infos_start_ = dex_register_maps_start_ + dex_register_maps_size_;
 
   return needed_size_;
@@ -313,6 +318,7 @@
         InlineInfoEntry inline_entry = inline_infos_.Get(depth + entry.inline_infos_start_index);
         inline_info.SetMethodIndexAtDepth(depth, inline_entry.method_index);
         inline_info.SetDexPcAtDepth(depth, inline_entry.dex_pc);
+        inline_info.SetInvokeTypeAtDepth(depth, inline_entry.invoke_type);
         if (inline_entry.num_dex_registers == 0) {
           // No dex map available.
           inline_info.SetDexRegisterMapOffsetAtDepth(depth, StackMap::kNoDexRegisterMap);
diff --git a/compiler/optimizing/stack_map_stream.h b/compiler/optimizing/stack_map_stream.h
index 4c03f9f..0af983b 100644
--- a/compiler/optimizing/stack_map_stream.h
+++ b/compiler/optimizing/stack_map_stream.h
@@ -104,6 +104,7 @@
   struct InlineInfoEntry {
     uint32_t dex_pc;
     uint32_t method_index;
+    InvokeType invoke_type;
     uint32_t num_dex_registers;
     BitVector* live_dex_registers_mask;
     size_t dex_register_locations_start_index;
@@ -121,6 +122,7 @@
 
   void BeginInlineInfoEntry(uint32_t method_index,
                             uint32_t dex_pc,
+                            InvokeType invoke_type,
                             uint32_t num_dex_registers);
   void EndInlineInfoEntry();
 
diff --git a/compiler/optimizing/stack_map_test.cc b/compiler/optimizing/stack_map_test.cc
index e04fa98..98e14ea 100644
--- a/compiler/optimizing/stack_map_test.cc
+++ b/compiler/optimizing/stack_map_test.cc
@@ -128,9 +128,9 @@
   stream.BeginStackMapEntry(0, 64, 0x3, &sp_mask1, number_of_dex_registers, 2);
   stream.AddDexRegisterEntry(Kind::kInStack, 0);         // Short location.
   stream.AddDexRegisterEntry(Kind::kConstant, -2);       // Large location.
-  stream.BeginInlineInfoEntry(82, 3, number_of_dex_registers_in_inline_info);
+  stream.BeginInlineInfoEntry(82, 3, kDirect, number_of_dex_registers_in_inline_info);
   stream.EndInlineInfoEntry();
-  stream.BeginInlineInfoEntry(42, 2, number_of_dex_registers_in_inline_info);
+  stream.BeginInlineInfoEntry(42, 2, kStatic, number_of_dex_registers_in_inline_info);
   stream.EndInlineInfoEntry();
   stream.EndStackMapEntry();
 
@@ -218,6 +218,8 @@
     ASSERT_EQ(42u, inline_info.GetMethodIndexAtDepth(1));
     ASSERT_EQ(3u, inline_info.GetDexPcAtDepth(0));
     ASSERT_EQ(2u, inline_info.GetDexPcAtDepth(1));
+    ASSERT_EQ(kDirect, inline_info.GetInvokeTypeAtDepth(0));
+    ASSERT_EQ(kStatic, inline_info.GetInvokeTypeAtDepth(1));
   }
 
   // Second stack map.
@@ -519,10 +521,10 @@
   stream.AddDexRegisterEntry(Kind::kInStack, 0);
   stream.AddDexRegisterEntry(Kind::kConstant, 4);
 
-  stream.BeginInlineInfoEntry(42, 2, 1);
+  stream.BeginInlineInfoEntry(42, 2, kStatic, 1);
   stream.AddDexRegisterEntry(Kind::kInStack, 8);
   stream.EndInlineInfoEntry();
-  stream.BeginInlineInfoEntry(82, 3, 3);
+  stream.BeginInlineInfoEntry(82, 3, kStatic, 3);
   stream.AddDexRegisterEntry(Kind::kInStack, 16);
   stream.AddDexRegisterEntry(Kind::kConstant, 20);
   stream.AddDexRegisterEntry(Kind::kInRegister, 15);
@@ -535,15 +537,15 @@
   stream.AddDexRegisterEntry(Kind::kInStack, 56);
   stream.AddDexRegisterEntry(Kind::kConstant, 0);
 
-  stream.BeginInlineInfoEntry(42, 2, 1);
+  stream.BeginInlineInfoEntry(42, 2, kDirect, 1);
   stream.AddDexRegisterEntry(Kind::kInStack, 12);
   stream.EndInlineInfoEntry();
-  stream.BeginInlineInfoEntry(82, 3, 3);
+  stream.BeginInlineInfoEntry(82, 3, kStatic, 3);
   stream.AddDexRegisterEntry(Kind::kInStack, 80);
   stream.AddDexRegisterEntry(Kind::kConstant, 10);
   stream.AddDexRegisterEntry(Kind::kInRegister, 5);
   stream.EndInlineInfoEntry();
-  stream.BeginInlineInfoEntry(52, 5, 0);
+  stream.BeginInlineInfoEntry(52, 5, kVirtual, 0);
   stream.EndInlineInfoEntry();
 
   stream.EndStackMapEntry();
@@ -559,12 +561,12 @@
   stream.AddDexRegisterEntry(Kind::kInStack, 56);
   stream.AddDexRegisterEntry(Kind::kConstant, 0);
 
-  stream.BeginInlineInfoEntry(42, 2, 0);
+  stream.BeginInlineInfoEntry(42, 2, kVirtual, 0);
   stream.EndInlineInfoEntry();
-  stream.BeginInlineInfoEntry(52, 5, 1);
+  stream.BeginInlineInfoEntry(52, 5, kInterface, 1);
   stream.AddDexRegisterEntry(Kind::kInRegister, 2);
   stream.EndInlineInfoEntry();
-  stream.BeginInlineInfoEntry(52, 10, 2);
+  stream.BeginInlineInfoEntry(52, 10, kStatic, 2);
   stream.AddDexRegisterEntry(Kind::kNone, 0);
   stream.AddDexRegisterEntry(Kind::kInRegister, 3);
   stream.EndInlineInfoEntry();
@@ -590,8 +592,10 @@
     ASSERT_EQ(2u, if0.GetDepth());
     ASSERT_EQ(2u, if0.GetDexPcAtDepth(0));
     ASSERT_EQ(42u, if0.GetMethodIndexAtDepth(0));
+    ASSERT_EQ(kStatic, if0.GetInvokeTypeAtDepth(0));
     ASSERT_EQ(3u, if0.GetDexPcAtDepth(1));
     ASSERT_EQ(82u, if0.GetMethodIndexAtDepth(1));
+    ASSERT_EQ(kStatic, if0.GetInvokeTypeAtDepth(1));
 
     DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if0, 1);
     ASSERT_EQ(8, dex_registers1.GetStackOffsetInBytes(0, 1, ci));
@@ -614,10 +618,13 @@
     ASSERT_EQ(3u, if1.GetDepth());
     ASSERT_EQ(2u, if1.GetDexPcAtDepth(0));
     ASSERT_EQ(42u, if1.GetMethodIndexAtDepth(0));
+    ASSERT_EQ(kDirect, if1.GetInvokeTypeAtDepth(0));
     ASSERT_EQ(3u, if1.GetDexPcAtDepth(1));
     ASSERT_EQ(82u, if1.GetMethodIndexAtDepth(1));
+    ASSERT_EQ(kStatic, if1.GetInvokeTypeAtDepth(1));
     ASSERT_EQ(5u, if1.GetDexPcAtDepth(2));
     ASSERT_EQ(52u, if1.GetMethodIndexAtDepth(2));
+    ASSERT_EQ(kVirtual, if1.GetInvokeTypeAtDepth(2));
 
     DexRegisterMap dex_registers1 = ci.GetDexRegisterMapAtDepth(0, if1, 1);
     ASSERT_EQ(12, dex_registers1.GetStackOffsetInBytes(0, 1, ci));
@@ -652,10 +659,13 @@
     ASSERT_EQ(3u, if2.GetDepth());
     ASSERT_EQ(2u, if2.GetDexPcAtDepth(0));
     ASSERT_EQ(42u, if2.GetMethodIndexAtDepth(0));
+    ASSERT_EQ(kVirtual, if2.GetInvokeTypeAtDepth(0));
     ASSERT_EQ(5u, if2.GetDexPcAtDepth(1));
     ASSERT_EQ(52u, if2.GetMethodIndexAtDepth(1));
+    ASSERT_EQ(kInterface, if2.GetInvokeTypeAtDepth(1));
     ASSERT_EQ(10u, if2.GetDexPcAtDepth(2));
     ASSERT_EQ(52u, if2.GetMethodIndexAtDepth(2));
+    ASSERT_EQ(kStatic, if2.GetInvokeTypeAtDepth(2));
 
     ASSERT_FALSE(if2.HasDexRegisterMapAtDepth(0));
 
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index eca6f5a..0086fe8 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -16,11 +16,11 @@
 
 #include "assembler_arm.h"
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "offsets.h"
 #include "thread.h"
-#include "utils.h"
 
 namespace art {
 namespace arm {
@@ -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 a19a764..350efca 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -19,13 +19,13 @@
 
 #include <vector>
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "base/value_object.h"
 #include "constants_arm.h"
 #include "utils/arm/managed_register_arm.h"
 #include "utils/assembler.h"
 #include "offsets.h"
-#include "utils.h"
 
 namespace art {
 namespace arm {
@@ -530,7 +530,7 @@
   // Branch instructions.
   virtual void b(Label* label, Condition cond = AL) = 0;
   virtual void b(NearLabel* label, Condition cond = AL) {
-    b(reinterpret_cast<Label*>(label), cond);
+    b(static_cast<Label*>(label), cond);
   }
   virtual void bl(Label* label, Condition cond = AL) = 0;
   virtual void blx(Register rm, Condition cond = AL) = 0;
@@ -668,7 +668,7 @@
 
   virtual void CompareAndBranchIfZero(Register r, Label* label) = 0;
   virtual void CompareAndBranchIfZero(Register r, NearLabel* label) {
-    CompareAndBranchIfZero(r, reinterpret_cast<Label*>(label));
+    CompareAndBranchIfZero(r, static_cast<Label*>(label));
   }
   virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0;
 
@@ -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/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc
index 6e165fc..cdf62bf 100644
--- a/compiler/utils/arm/assembler_arm32.cc
+++ b/compiler/utils/arm/assembler_arm32.cc
@@ -16,11 +16,11 @@
 
 #include "assembler_arm32.h"
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "offsets.h"
 #include "thread.h"
-#include "utils.h"
 
 namespace art {
 namespace arm {
diff --git a/compiler/utils/arm/assembler_arm32.h b/compiler/utils/arm/assembler_arm32.h
index 4564767..3164623 100644
--- a/compiler/utils/arm/assembler_arm32.h
+++ b/compiler/utils/arm/assembler_arm32.h
@@ -24,7 +24,6 @@
 #include "utils/arm/managed_register_arm.h"
 #include "utils/arm/assembler_arm.h"
 #include "offsets.h"
-#include "utils.h"
 
 namespace art {
 namespace arm {
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index c3b19da..26cb6c3 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -16,11 +16,11 @@
 
 #include "assembler_thumb2.h"
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "offsets.h"
 #include "thread.h"
-#include "utils.h"
 
 namespace art {
 namespace arm {
@@ -678,7 +678,7 @@
 
 
 void Thumb2Assembler::b(NearLabel* label, Condition cond) {
-  EmitBranch(cond, label, false, false, true /* is_near */);
+  EmitBranch(cond, label, false, false, /* is_near */ true);
 }
 
 
@@ -1375,6 +1375,7 @@
 
 
 uint16_t Thumb2Assembler::EmitCompareAndBranch(Register rn, uint16_t prev, bool n) {
+  CHECK(IsLowRegister(rn));
   uint32_t location = buffer_.Size();
 
   // This is always unresolved as it must be a forward branch.
@@ -2205,6 +2206,9 @@
   if (label->IsBound()) {
     LOG(FATAL) << "cbz can only be used to branch forwards";
     UNREACHABLE();
+  } else if (IsHighRegister(rn)) {
+    LOG(FATAL) << "cbz can only be used with low registers";
+    UNREACHABLE();
   } else {
     uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), false);
     label->LinkTo(branchid);
@@ -2217,6 +2221,9 @@
   if (label->IsBound()) {
     LOG(FATAL) << "cbnz can only be used to branch forwards";
     UNREACHABLE();
+  } else if (IsHighRegister(rn)) {
+    LOG(FATAL) << "cbnz can only be used with low registers";
+    UNREACHABLE();
   } else {
     uint16_t branchid = EmitCompareAndBranch(rn, static_cast<uint16_t>(label->position_), true);
     label->LinkTo(branchid);
@@ -2747,7 +2754,7 @@
 
 
 void Thumb2Assembler::CompareAndBranchIfZero(Register r, Label* label) {
-  if (CanRelocateBranches()) {
+  if (CanRelocateBranches() && IsLowRegister(r)) {
     cbz(r, label);
   } else {
     cmp(r, ShifterOperand(0));
@@ -2757,12 +2764,17 @@
 
 
 void Thumb2Assembler::CompareAndBranchIfZero(Register r, NearLabel* label) {
-  cbz(r, label);
+  if (IsLowRegister(r)) {
+    cbz(r, label);
+  } else {
+    cmp(r, ShifterOperand(0));
+    b(label, EQ);
+  }
 }
 
 
 void Thumb2Assembler::CompareAndBranchIfNonZero(Register r, Label* label) {
-  if (CanRelocateBranches()) {
+  if (CanRelocateBranches() && IsLowRegister(r)) {
     cbnz(r, label);
   } else {
     cmp(r, ShifterOperand(0));
diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h
index e8def73..2382b74 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -24,7 +24,6 @@
 #include "utils/arm/managed_register_arm.h"
 #include "utils/arm/assembler_arm.h"
 #include "offsets.h"
-#include "utils.h"
 
 namespace art {
 namespace arm {
@@ -573,6 +572,7 @@
       } else {
         if (kIsDebugBuild) {
           if (old_target == kUnresolved) {
+            // Check that the size has not increased.
             DCHECK(!(CalculateSize() == k32Bit && size_ == k16Bit));
           } else {
             DCHECK(CalculateSize() == size_);
diff --git a/compiler/utils/arm64/assembler_arm64.cc b/compiler/utils/arm64/assembler_arm64.cc
index 98702a2..cc78002 100644
--- a/compiler/utils/arm64/assembler_arm64.cc
+++ b/compiler/utils/arm64/assembler_arm64.cc
@@ -19,7 +19,6 @@
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "offsets.h"
 #include "thread.h"
-#include "utils.h"
 
 using namespace vixl;  // NOLINT(build/namespaces)
 
@@ -52,11 +51,11 @@
 }
 
 void Arm64Assembler::GetCurrentThread(ManagedRegister tr) {
-  ___ Mov(reg_x(tr.AsArm64().AsXRegister()), reg_x(ETR));
+  ___ Mov(reg_x(tr.AsArm64().AsXRegister()), reg_x(TR));
 }
 
 void Arm64Assembler::GetCurrentThread(FrameOffset offset, ManagedRegister /* scratch */) {
-  StoreToOffset(ETR, SP, offset.Int32Value());
+  StoreToOffset(TR, SP, offset.Int32Value());
 }
 
 // See Arm64 PCS Section 5.2.2.1.
@@ -168,7 +167,7 @@
   Arm64ManagedRegister scratch = m_scratch.AsArm64();
   CHECK(scratch.IsXRegister()) << scratch;
   LoadImmediate(scratch.AsXRegister(), imm);
-  StoreToOffset(scratch.AsXRegister(), ETR, offs.Int32Value());
+  StoreToOffset(scratch.AsXRegister(), TR, offs.Int32Value());
 }
 
 void Arm64Assembler::StoreStackOffsetToThread64(ThreadOffset<8> tr_offs,
@@ -177,14 +176,14 @@
   Arm64ManagedRegister scratch = m_scratch.AsArm64();
   CHECK(scratch.IsXRegister()) << scratch;
   AddConstant(scratch.AsXRegister(), SP, fr_offs.Int32Value());
-  StoreToOffset(scratch.AsXRegister(), ETR, tr_offs.Int32Value());
+  StoreToOffset(scratch.AsXRegister(), TR, tr_offs.Int32Value());
 }
 
 void Arm64Assembler::StoreStackPointerToThread64(ThreadOffset<8> tr_offs) {
   vixl::UseScratchRegisterScope temps(vixl_masm_);
   vixl::Register temp = temps.AcquireX();
   ___ Mov(temp, reg_x(SP));
-  ___ Str(temp, MEM_OP(reg_x(ETR), tr_offs.Int32Value()));
+  ___ Str(temp, MEM_OP(reg_x(TR), tr_offs.Int32Value()));
 }
 
 void Arm64Assembler::StoreSpanning(FrameOffset dest_off, ManagedRegister m_source,
@@ -285,7 +284,7 @@
 }
 
 void Arm64Assembler::LoadFromThread64(ManagedRegister m_dst, ThreadOffset<8> src, size_t size) {
-  return Load(m_dst.AsArm64(), ETR, src.Int32Value(), size);
+  return Load(m_dst.AsArm64(), TR, src.Int32Value(), size);
 }
 
 void Arm64Assembler::LoadRef(ManagedRegister m_dst, FrameOffset offs) {
@@ -294,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)));
   }
@@ -320,7 +319,7 @@
 void Arm64Assembler::LoadRawPtrFromThread64(ManagedRegister m_dst, ThreadOffset<8> offs) {
   Arm64ManagedRegister dst = m_dst.AsArm64();
   CHECK(dst.IsXRegister()) << dst;
-  LoadFromOffset(dst.AsXRegister(), ETR, offs.Int32Value());
+  LoadFromOffset(dst.AsXRegister(), TR, offs.Int32Value());
 }
 
 // Copying routines.
@@ -358,7 +357,7 @@
                                           ManagedRegister m_scratch) {
   Arm64ManagedRegister scratch = m_scratch.AsArm64();
   CHECK(scratch.IsXRegister()) << scratch;
-  LoadFromOffset(scratch.AsXRegister(), ETR, tr_offs.Int32Value());
+  LoadFromOffset(scratch.AsXRegister(), TR, tr_offs.Int32Value());
   StoreToOffset(scratch.AsXRegister(), SP, fr_offs.Int32Value());
 }
 
@@ -368,7 +367,7 @@
   Arm64ManagedRegister scratch = m_scratch.AsArm64();
   CHECK(scratch.IsXRegister()) << scratch;
   LoadFromOffset(scratch.AsXRegister(), SP, fr_offs.Int32Value());
-  StoreToOffset(scratch.AsXRegister(), ETR, tr_offs.Int32Value());
+  StoreToOffset(scratch.AsXRegister(), TR, tr_offs.Int32Value());
 }
 
 void Arm64Assembler::CopyRef(FrameOffset dest, FrameOffset src,
@@ -536,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()));
 }
@@ -545,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.
@@ -572,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) {
@@ -591,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;
@@ -611,7 +611,7 @@
   Arm64ManagedRegister scratch = m_scratch.AsArm64();
   Arm64Exception *current_exception = new Arm64Exception(scratch, stack_adjust);
   exception_blocks_.push_back(current_exception);
-  LoadFromOffset(scratch.AsXRegister(), ETR, Thread::ExceptionOffset<8>().Int32Value());
+  LoadFromOffset(scratch.AsXRegister(), TR, Thread::ExceptionOffset<8>().Int32Value());
   ___ Cbnz(reg_x(scratch.AsXRegister()), current_exception->Entry());
 }
 
@@ -628,12 +628,7 @@
   // Pass exception object as argument.
   // Don't care about preserving X0 as this won't return.
   ___ Mov(reg_x(X0), reg_x(exception->scratch_.AsXRegister()));
-  ___ Ldr(temp, MEM_OP(reg_x(ETR), QUICK_ENTRYPOINT_OFFSET(8, pDeliverException).Int32Value()));
-
-  // Move ETR(Callee saved) back to TR(Caller saved) reg. We use ETR on calls
-  // to external functions that might trash TR. We do not need the original
-  // ETR(X21) saved in BuildFrame().
-  ___ Mov(reg_x(TR), reg_x(ETR));
+  ___ Ldr(temp, MEM_OP(reg_x(TR), QUICK_ENTRYPOINT_OFFSET(8, pDeliverException).Int32Value()));
 
   ___ Blr(temp);
   // Call should never return.
@@ -707,27 +702,21 @@
 
   // 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.
   SpillRegisters(core_reg_list, frame_size - core_reg_size);
   SpillRegisters(fp_reg_list, frame_size - core_reg_size - fp_reg_size);
 
-  // Note: This is specific to JNI method frame.
-  // We will need to move TR(Caller saved in AAPCS) to ETR(Callee saved in AAPCS). The original
-  // (ETR)X21 has been saved on stack. In this way, we can restore TR later.
-  DCHECK(!core_reg_list.IncludesAliasOf(reg_x(TR)));
-  DCHECK(core_reg_list.IncludesAliasOf(reg_x(ETR)));
-  ___ Mov(reg_x(ETR), reg_x(TR));
+  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()) {
@@ -769,14 +758,10 @@
 
   // 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);
 
-  // Note: This is specific to JNI method frame.
-  // Restore TR(Caller saved in AAPCS) from ETR(Callee saved in AAPCS).
-  DCHECK(!core_reg_list.IncludesAliasOf(reg_x(TR)));
-  DCHECK(core_reg_list.IncludesAliasOf(reg_x(ETR)));
-  ___ Mov(reg_x(TR), reg_x(ETR));
+  DCHECK(core_reg_list.IncludesAliasOf(reg_x(TR)));
 
   cfi_.RememberState();
 
diff --git a/compiler/utils/arm64/assembler_arm64.h b/compiler/utils/arm64/assembler_arm64.h
index e47b531..fa9faed 100644
--- a/compiler/utils/arm64/assembler_arm64.h
+++ b/compiler/utils/arm64/assembler_arm64.h
@@ -26,7 +26,6 @@
 #include "utils/arm64/managed_register_arm64.h"
 #include "utils/assembler.h"
 #include "offsets.h"
-#include "utils.h"
 
 // TODO: make vixl clean wrt -Wshadow.
 #pragma GCC diagnostic push
@@ -114,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/arm64/managed_register_arm64.h b/compiler/utils/arm64/managed_register_arm64.h
index 62c1d4d..dbcd8c5 100644
--- a/compiler/utils/arm64/managed_register_arm64.h
+++ b/compiler/utils/arm64/managed_register_arm64.h
@@ -117,8 +117,7 @@
 
   bool IsSRegister() const {
     CHECK(IsValidManagedRegister());
-    const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds +
-                            kNumberOfDRegIds);
+    const int test = id_ - (kNumberOfXRegIds + kNumberOfWRegIds + kNumberOfDRegIds);
     return (0 <= test) && (test < kNumberOfSRegIds);
   }
 
diff --git a/compiler/utils/arm64/managed_register_arm64_test.cc b/compiler/utils/arm64/managed_register_arm64_test.cc
index 32c2e62..e27115d 100644
--- a/compiler/utils/arm64/managed_register_arm64_test.cc
+++ b/compiler/utils/arm64/managed_register_arm64_test.cc
@@ -623,7 +623,7 @@
   EXPECT_TRUE(vixl::x29.Is(Arm64Assembler::reg_x(X29)));
   EXPECT_TRUE(vixl::x30.Is(Arm64Assembler::reg_x(X30)));
 
-  EXPECT_TRUE(vixl::x18.Is(Arm64Assembler::reg_x(TR)));
+  EXPECT_TRUE(vixl::x19.Is(Arm64Assembler::reg_x(TR)));
   EXPECT_TRUE(vixl::ip0.Is(Arm64Assembler::reg_x(IP0)));
   EXPECT_TRUE(vixl::ip1.Is(Arm64Assembler::reg_x(IP1)));
   EXPECT_TRUE(vixl::x29.Is(Arm64Assembler::reg_x(FP)));
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/assembler_test_base.h b/compiler/utils/assembler_test_base.h
index 3341151..c8b3fe5 100644
--- a/compiler/utils/assembler_test_base.h
+++ b/compiler/utils/assembler_test_base.h
@@ -17,14 +17,15 @@
 #ifndef ART_COMPILER_UTILS_ASSEMBLER_TEST_BASE_H_
 #define ART_COMPILER_UTILS_ASSEMBLER_TEST_BASE_H_
 
-#include "common_runtime_test.h"  // For ScratchFile
-
 #include <cstdio>
 #include <cstdlib>
 #include <fstream>
 #include <iterator>
 #include <sys/stat.h>
 
+#include "common_runtime_test.h"  // For ScratchFile
+#include "utils.h"
+
 namespace art {
 
 // If you want to take a look at the differences between the ART assembler and GCC, set this flag
@@ -215,9 +216,9 @@
 
     bool success = Exec(args, error_msg);
     if (!success) {
-      LOG(INFO) << "Assembler command line:";
+      LOG(ERROR) << "Assembler command line:";
       for (std::string arg : args) {
-        LOG(INFO) << arg;
+        LOG(ERROR) << arg;
       }
     }
     return success;
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index 7738627..1a2c9a9 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -1338,6 +1338,24 @@
   delete assembler;
 }
 
+TEST(Thumb2AssemblerTest, CompareAndBranch) {
+  arm::Thumb2Assembler* assembler = static_cast<arm::Thumb2Assembler*>(Assembler::Create(kThumb2));
+
+  arm::NearLabel label;
+  __ CompareAndBranchIfZero(arm::R0, &label);
+  __ CompareAndBranchIfZero(arm::R11, &label);
+  __ CompareAndBranchIfNonZero(arm::R0, &label);
+  __ CompareAndBranchIfNonZero(arm::R11, &label);
+  __ Bind(&label);
+
+  size_t cs = __ CodeSize();
+  std::vector<uint8_t> managed_code(cs);
+  MemoryRegion code(&managed_code[0], managed_code.size());
+  __ FinalizeInstructions(code);
+  dump(managed_code, "CompareAndBranch");
+  delete assembler;
+}
+
 #undef __
 }  // namespace arm
 }  // namespace art
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index 3d03234..841d6a0 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -4822,6 +4822,16 @@
   "  30:   f8a4 0040       strh.w  r0, [r4, #64]   ; 0x40\n",
   nullptr
 };
+const char* CompareAndBranchResults[] = {
+  "  0: b130        cbz r0, 10 <CompareAndBranch+0x10>\n",
+  "  2: f1bb 0f00   cmp.w fp, #0\n",
+  "  6: d003        beq.n 10 <CompareAndBranch+0x10>\n",
+  "  8: b910        cbnz r0, 10 <CompareAndBranch+0x10>\n",
+  "  a: f1bb 0f00   cmp.w fp, #0\n",
+  "  e: d1ff        bne.n 10 <CompareAndBranch+0x10>\n",
+  nullptr
+};
+
 std::map<std::string, const char**> test_results;
 void setup_results() {
     test_results["SimpleMov"] = SimpleMovResults;
@@ -4869,4 +4879,5 @@
     test_results["LoadStoreRegOffset"] = LoadStoreRegOffsetResults;
     test_results["LoadStoreLiteral"] = LoadStoreLiteralResults;
     test_results["LoadStoreLimits"] = LoadStoreLimitsResults;
+    test_results["CompareAndBranch"] = CompareAndBranchResults;
 }
diff --git a/compiler/utils/dedupe_set.h b/compiler/utils/dedupe_set.h
index a9a5781..8cdb180 100644
--- a/compiler/utils/dedupe_set.h
+++ b/compiler/utils/dedupe_set.h
@@ -26,6 +26,7 @@
 #include "base/mutex.h"
 #include "base/stl_util.h"
 #include "base/stringprintf.h"
+#include "base/time_utils.h"
 #include "utils/swap_space.h"
 
 namespace art {
diff --git a/compiler/utils/dex_cache_arrays_layout-inl.h b/compiler/utils/dex_cache_arrays_layout-inl.h
index 2c50c96..fec981a 100644
--- a/compiler/utils/dex_cache_arrays_layout-inl.h
+++ b/compiler/utils/dex_cache_arrays_layout-inl.h
@@ -19,17 +19,11 @@
 
 #include "dex_cache_arrays_layout.h"
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "globals.h"
 #include "mirror/array-inl.h"
 #include "primitive.h"
-#include "utils.h"
-
-namespace mirror {
-class ArtMethod;
-class Class;
-class String;
-}  // namespace mirror
 
 namespace art {
 
@@ -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 709a911..e55b461 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -16,6 +16,7 @@
 
 #include "assembler_mips.h"
 
+#include "base/bit_utils.h"
 #include "base/casts.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "memory_region.h"
@@ -695,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 d4acf03..7b0fc39 100644
--- a/compiler/utils/mips/assembler_mips.h
+++ b/compiler/utils/mips/assembler_mips.h
@@ -25,7 +25,6 @@
 #include "managed_register_mips.h"
 #include "utils/assembler.h"
 #include "offsets.h"
-#include "utils.h"
 
 namespace art {
 namespace mips {
@@ -190,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 5e9653d..a8b55d1 100644
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ b/compiler/utils/mips64/assembler_mips64.cc
@@ -16,6 +16,7 @@
 
 #include "assembler_mips64.h"
 
+#include "base/bit_utils.h"
 #include "base/casts.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 #include "memory_region.h"
@@ -116,7 +117,7 @@
 
 int32_t Mips64Assembler::EncodeBranchOffset(int offset, int32_t inst, bool is_jump) {
   CHECK_ALIGNED(offset, 4);
-  CHECK(IsInt(POPCOUNT(kBranchOffsetMask), offset)) << offset;
+  CHECK(IsInt<POPCOUNT(kBranchOffsetMask)>(offset)) << offset;
 
   // Properly preserve only the bits supported in the instruction.
   offset >>= 2;
@@ -600,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);
@@ -749,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());
   }
 }
@@ -1003,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 2d7c661..38419ab 100644
--- a/compiler/utils/mips64/assembler_mips64.h
+++ b/compiler/utils/mips64/assembler_mips64.h
@@ -25,7 +25,6 @@
 #include "managed_register_mips64.h"
 #include "utils/assembler.h"
 #include "offsets.h"
-#include "utils.h"
 
 namespace art {
 namespace mips64 {
@@ -189,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/swap_space.h b/compiler/utils/swap_space.h
index 1f8f5da..691df4a 100644
--- a/compiler/utils/swap_space.h
+++ b/compiler/utils/swap_space.h
@@ -28,7 +28,6 @@
 #include "base/macros.h"
 #include "base/mutex.h"
 #include "mem_map.h"
-#include "utils.h"
 
 namespace art {
 
diff --git a/compiler/utils/test_dex_file_builder.h b/compiler/utils/test_dex_file_builder.h
index ab039aa..b1d7b4c 100644
--- a/compiler/utils/test_dex_file_builder.h
+++ b/compiler/utils/test_dex_file_builder.h
@@ -22,8 +22,9 @@
 #include <map>
 #include <vector>
 
+#include "base/bit_utils.h"
+#include "base/logging.h"
 #include "dex_file.h"
-#include "utils.h"
 
 namespace art {
 
diff --git a/compiler/utils/test_dex_file_builder_test.cc b/compiler/utils/test_dex_file_builder_test.cc
index ee6e35d..7a424a2 100644
--- a/compiler/utils/test_dex_file_builder_test.cc
+++ b/compiler/utils/test_dex_file_builder_test.cc
@@ -18,6 +18,7 @@
 
 #include "dex_file-inl.h"
 #include "gtest/gtest.h"
+#include "utils.h"
 
 namespace art {
 
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 136b0cb..1c1c023 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -18,13 +18,13 @@
 #define ART_COMPILER_UTILS_X86_ASSEMBLER_X86_H_
 
 #include <vector>
+#include "base/bit_utils.h"
 #include "base/macros.h"
 #include "constants_x86.h"
 #include "globals.h"
 #include "managed_register_x86.h"
 #include "offsets.h"
 #include "utils/assembler.h"
-#include "utils.h"
 
 namespace art {
 namespace x86 {
@@ -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 162714a..6b2b65d 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -18,13 +18,14 @@
 #define ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_
 
 #include <vector>
+
+#include "base/bit_utils.h"
 #include "base/macros.h"
 #include "constants_x86_64.h"
 #include "globals.h"
 #include "managed_register_x86_64.h"
 #include "offsets.h"
 #include "utils/assembler.h"
-#include "utils.h"
 
 namespace art {
 namespace x86_64 {
@@ -667,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 0be4d63..b86bc85 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -20,9 +20,9 @@
 #include <map>
 #include <random>
 
+#include "base/bit_utils.h"
 #include "base/stl_util.h"
 #include "utils/assembler_test.h"
-#include "utils.h"
 
 namespace art {
 
@@ -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 43bec37..d45ab1b 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -35,12 +35,14 @@
 #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"
 #include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/stringpiece.h"
+#include "base/time_utils.h"
 #include "base/timing_logger.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
@@ -60,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"
@@ -229,14 +230,14 @@
   UsageError("");
   UsageError("  --no-include-patch-information: Do not include patching information.");
   UsageError("");
-  UsageError("  --include-debug-symbols: Include ELF symbols in this oat file");
+  UsageError("  -g");
+  UsageError("  --generate-debug-info: Generate debug information for native debugging,");
+  UsageError("      such as stack unwinding information, ELF symbols and DWARF sections.");
+  UsageError("      This generates all the available information. Unneeded parts can be");
+  UsageError("      stripped using standard command line tools such as strip or objcopy.");
+  UsageError("      (enabled by default in debug builds, disabled by default otherwise)");
   UsageError("");
-  UsageError("  --no-include-debug-symbols: Do not include ELF symbols in this oat file");
-  UsageError("");
-  UsageError("  --include-cfi: Include call frame information in the .eh_frame section.");
-  UsageError("      The --include-debug-symbols option implies --include-cfi.");
-  UsageError("");
-  UsageError("  --no-include-cfi: Do not include call frame information in the .eh_frame section.");
+  UsageError("  --no-generate-debug-info: Do not generate debug information for native debugging.");
   UsageError("");
   UsageError("  --runtime-arg <argument>: used to specify various arguments for the runtime,");
   UsageError("      such as initial heap size, maximum heap size, and verbose output.");
@@ -498,8 +499,7 @@
 
     bool debuggable = false;
     bool include_patch_information = CompilerOptions::kDefaultIncludePatchInformation;
-    bool include_debug_symbols = kIsDebugBuild;
-    bool include_cfi = kIsDebugBuild;
+    bool generate_debug_info = kIsDebugBuild;
     bool watch_dog_enabled = true;
     bool abort_on_hard_verifier_error = false;
     bool requested_specific_compiler = false;
@@ -681,18 +681,13 @@
         dump_cfg_file_name_ = option.substr(strlen("--dump-cfg=")).data();
       } else if (option == "--dump-stats") {
         dump_stats_ = true;
-      } else if (option == "--include-debug-symbols" || option == "--no-strip-symbols") {
-        include_debug_symbols = true;
-      } else if (option == "--no-include-debug-symbols" || option == "--strip-symbols") {
-        include_debug_symbols = false;
-      } else if (option == "--include-cfi") {
-        include_cfi = true;
-      } else if (option == "--no-include-cfi") {
-        include_cfi = false;
+      } else if (option == "--generate-debug-info" || option == "-g") {
+        generate_debug_info = true;
+      } else if (option == "--no-generate-debug-info") {
+        generate_debug_info = false;
       } else if (option == "--debuggable") {
         debuggable = true;
-        include_debug_symbols = true;
-        include_cfi = true;
+        generate_debug_info = true;
       } else if (option.starts_with("--profile-file=")) {
         profile_file_ = option.substr(strlen("--profile-file=")).data();
         VLOG(compiler) << "dex2oat: profile file is " << profile_file_;
@@ -932,10 +927,6 @@
         break;
     }
 
-    if (debuggable) {
-      // TODO: Consider adding CFI info and symbols here.
-    }
-
     compiler_options_.reset(new CompilerOptions(compiler_filter,
                                                 huge_method_threshold,
                                                 large_method_threshold,
@@ -945,8 +936,7 @@
                                                 include_patch_information,
                                                 top_k_profile_threshold,
                                                 debuggable,
-                                                include_debug_symbols,
-                                                include_cfi,
+                                                generate_debug_info,
                                                 implicit_null_checks,
                                                 implicit_so_checks,
                                                 implicit_suspend_checks,
diff --git a/disassembler/disassembler_arm64.cc b/disassembler/disassembler_arm64.cc
index d195efc..348b2a5 100644
--- a/disassembler/disassembler_arm64.cc
+++ b/disassembler/disassembler_arm64.cc
@@ -31,8 +31,7 @@
 // runtime/arch/arm64/registers_arm64.h. We do not include that file to
 // avoid a dependency on libart.
 enum {
-  TR  = 18,
-  ETR = 21,
+  TR  = 19,
   IP0 = 16,
   IP1 = 17,
   FP  = 29,
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 949c2cb..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);
@@ -1035,7 +1037,7 @@
   void DumpCodeInfo(std::ostream& os,
                     const CodeInfo& code_info,
                     const DexFile::CodeItem& code_item) {
-    code_info.Dump(os, code_item.registers_size_);
+    code_info.Dump(os, code_item.registers_size_, true);
   }
 
   // Display a vmap table.
@@ -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);
 };
@@ -2302,7 +2382,7 @@
         "  --dump:raw_mapping_table enables dumping of the mapping table.\n"
         "      Example: --dump:raw_mapping_table\n"
         "\n"
-        "  --dump:raw_mapping_table enables dumping of the GC map.\n"
+        "  --dump:raw_gc_map enables dumping of the GC map.\n"
         "      Example: --dump:raw_gc_map\n"
         "\n"
         "  --no-dump:vmap may be used to disable vmap dumping.\n"
diff --git a/oatdump/oatdump_test.cc b/oatdump/oatdump_test.cc
new file mode 100644
index 0000000..b34bc84
--- /dev/null
+++ b/oatdump/oatdump_test.cc
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include "common_runtime_test.h"
+
+#include "base/stringprintf.h"
+#include "runtime/arch/instruction_set.h"
+#include "runtime/gc/heap.h"
+#include "runtime/gc/space/image_space.h"
+#include "runtime/os.h"
+#include "runtime/utils.h"
+#include "utils.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace art {
+
+class OatDumpTest : public CommonRuntimeTest {
+ protected:
+  virtual void SetUp() {
+    CommonRuntimeTest::SetUp();
+    core_art_location_ = GetCoreArtLocation();
+    core_oat_location_ = GetSystemImageFilename(GetCoreOatLocation().c_str(), kRuntimeISA);
+  }
+
+  // Returns path to the oatdump binary.
+  std::string GetOatDumpFilePath() {
+    std::string root = GetTestAndroidRoot();
+    root += "/bin/oatdump";
+    if (kIsDebugBuild) {
+      root += "d";
+    }
+    return root;
+  }
+
+  enum Mode {
+    kModeOat,
+    kModeArt,
+    kModeSymbolize,
+  };
+
+  // Run the test with custom arguments.
+  bool Exec(Mode mode, const std::vector<std::string>& args, std::string* error_msg) {
+    std::string file_path = GetOatDumpFilePath();
+
+    EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
+
+    std::vector<std::string> exec_argv = { file_path };
+    if (mode == kModeSymbolize) {
+      exec_argv.push_back("--symbolize=" + core_oat_location_);
+      exec_argv.push_back("--output=" + core_oat_location_ + ".symbolize");
+    } else if (mode == kModeArt) {
+      exec_argv.push_back("--image=" + core_art_location_);
+      exec_argv.push_back("--output=/dev/null");
+    } else {
+      CHECK_EQ(static_cast<size_t>(mode), static_cast<size_t>(kModeOat));
+      exec_argv.push_back("--oat-file=" + core_oat_location_);
+      exec_argv.push_back("--output=/dev/null");
+    }
+    exec_argv.insert(exec_argv.end(), args.begin(), args.end());
+    return ::art::Exec(exec_argv, error_msg);
+  }
+
+ private:
+  std::string core_art_location_;
+  std::string core_oat_location_;
+};
+
+TEST_F(OatDumpTest, TestImage) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec(kModeArt, {}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestOatImage) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec(kModeOat, {}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestDumpRawMappingTable) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec(kModeArt, {"--dump:raw_mapping_table"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestDumpRawGcMap) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec(kModeArt, {"--dump:raw_gc_map"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestNoDumpVmap) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec(kModeArt, {"--no-dump:vmap"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestNoDisassemble) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec(kModeArt, {"--no-disassemble"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestListClasses) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec(kModeArt, {"--list-classes"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestListMethods) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec(kModeArt, {"--list-methods"}, &error_msg)) << error_msg;
+}
+
+TEST_F(OatDumpTest, TestSymbolize) {
+  std::string error_msg;
+  ASSERT_TRUE(Exec(kModeSymbolize, {}, &error_msg)) << error_msg;
+}
+
+}  // namespace art
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index ef84a17..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(reinterpret_cast<void*>(quick + delta_),
-                                                    pointer_size);
-  }
-  uintptr_t interpreter = reinterpret_cast<uintptr_t>(
-      object->GetEntryPointFromInterpreterPtrSize<kVerifyNone>(pointer_size));
-  if (interpreter != 0) {
-    copy->SetEntryPointFromInterpreterPtrSize(
-        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(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 86f9118..7b9c8bd 100644
--- a/patchoat/patchoat.h
+++ b/patchoat/patchoat.h
@@ -25,18 +25,18 @@
 #include "gc/accounting/space_bitmap.h"
 #include "gc/heap.h"
 #include "os.h"
-#include "utils.h"
 
 namespace art {
 
+class ArtMethod;
 class ImageHeader;
 class OatHeader;
 
 namespace mirror {
 class Object;
+class PointerArray;
 class Reference;
 class Class;
-class ArtMethod;
 }  // namespace mirror
 
 class PatchOat {
@@ -100,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*);
 
@@ -113,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_);
 
@@ -134,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 ece9d4b..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 \
@@ -32,6 +33,7 @@
   base/scoped_flock.cc \
   base/stringpiece.cc \
   base/stringprintf.cc \
+  base/time_utils.cc \
   base/timing_logger.cc \
   base/unix_file/fd_file.cc \
   base/unix_file/random_access_file_utils.cc \
@@ -101,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 \
@@ -316,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 5bd23d0..403d348 100644
--- a/runtime/arch/arm/context_arm.cc
+++ b/runtime/arch/arm/context_arm.cc
@@ -16,9 +16,9 @@
 
 #include "context_arm.h"
 
-#include "mirror/art_method-inl.h"
+#include "art_method-inl.h"
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
-#include "utils.h"
 
 namespace art {
 namespace arm {
@@ -26,12 +26,8 @@
 static constexpr uint32_t gZero = 0;
 
 void ArmContext::Reset() {
-  for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
-    gprs_[i] = nullptr;
-  }
-  for (size_t i = 0; i < kNumberOfSRegisters; i++) {
-    fprs_[i] = nullptr;
-  }
+  std::fill_n(gprs_, arraysize(gprs_), nullptr);
+  std::fill_n(fprs_, arraysize(fprs_), nullptr);
   gprs_[SP] = &sp_;
   gprs_[PC] = &pc_;
   // Initialize registers with easy to spot debug values.
@@ -40,31 +36,25 @@
 }
 
 void ArmContext::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
-  size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
-  size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
-  if (spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context
-    int j = 1;
-    for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
-      if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
-        gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
-        j++;
-      }
-    }
+  int spill_pos = 0;
+
+  // Core registers come first, from the highest down to the lowest.
+  uint32_t core_regs = frame_info.CoreSpillMask();
+  DCHECK_EQ(0u, core_regs & (static_cast<uint32_t>(-1) << kNumberOfCoreRegisters));
+  for (uint32_t core_reg : HighToLowBits(core_regs)) {
+    gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+    ++spill_pos;
   }
-  if (fp_spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context
-    int j = 1;
-    for (size_t i = 0; i < kNumberOfSRegisters; i++) {
-      if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
-        fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
-                                        frame_info.FrameSizeInBytes());
-        j++;
-      }
-    }
+  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
+
+  // FP registers come second, from the highest down to the lowest.
+  for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
+    fprs_[fp_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+    ++spill_pos;
   }
+  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
 }
 
 void ArmContext::SetGPR(uint32_t reg, uintptr_t value) {
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 3c145d7..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
@@ -890,10 +890,7 @@
      * dex method index.
      */
 ENTRY art_quick_imt_conflict_trampoline
-    ldr    r0, [sp, #0]            @ load caller Method*
-    ldr    r0, [r0, #MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET]  @ load dex_cache_resolved_methods
-    add    r0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET  @ get starting address of data
-    ldr    r0, [r0, r12, lsl 2]    @ load the target method
+    mov    r0, r12
     b art_quick_invoke_interface_trampoline
 END art_quick_imt_conflict_trampoline
 
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/arm/quick_method_frame_info_arm.h b/runtime/arch/arm/quick_method_frame_info_arm.h
index c1f3fc2..5580ee4 100644
--- a/runtime/arch/arm/quick_method_frame_info_arm.h
+++ b/runtime/arch/arm/quick_method_frame_info_arm.h
@@ -17,10 +17,10 @@
 #ifndef ART_RUNTIME_ARCH_ARM_QUICK_METHOD_FRAME_INFO_ARM_H_
 #define ART_RUNTIME_ARCH_ARM_QUICK_METHOD_FRAME_INFO_ARM_H_
 
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_arm.h"
 #include "runtime.h"  // for Runtime::CalleeSaveType.
-#include "utils.h"
 
 namespace art {
 namespace arm {
diff --git a/runtime/arch/arm64/asm_support_arm64.S b/runtime/arch/arm64/asm_support_arm64.S
index 39a8aa5..051f40b 100644
--- a/runtime/arch/arm64/asm_support_arm64.S
+++ b/runtime/arch/arm64/asm_support_arm64.S
@@ -22,9 +22,7 @@
 // Define special registers.
 
 // Register holding Thread::Current().
-#define xSELF x18
-// x18 is not preserved by aapcs64, save it on xETR(External Thread reg) for restore and later use.
-#define xETR x21
+#define xSELF x19
 // Frame Pointer
 #define xFP   x29
 // Link Register
diff --git a/runtime/arch/arm64/asm_support_arm64.h b/runtime/arch/arm64/asm_support_arm64.h
index 998f567..989ecc6 100644
--- a/runtime/arch/arm64/asm_support_arm64.h
+++ b/runtime/arch/arm64/asm_support_arm64.h
@@ -20,7 +20,7 @@
 #include "asm_support.h"
 
 #define FRAME_SIZE_SAVE_ALL_CALLEE_SAVE 176
-#define FRAME_SIZE_REFS_ONLY_CALLEE_SAVE 112
+#define FRAME_SIZE_REFS_ONLY_CALLEE_SAVE 96
 #define FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE 224
 
 #endif  // ART_RUNTIME_ARCH_ARM64_ASM_SUPPORT_ARM64_H_
diff --git a/runtime/arch/arm64/context_arm64.cc b/runtime/arch/arm64/context_arm64.cc
index ec9c122..60becc6 100644
--- a/runtime/arch/arm64/context_arm64.cc
+++ b/runtime/arch/arm64/context_arm64.cc
@@ -18,9 +18,9 @@
 
 #include "context_arm64.h"
 
-#include "mirror/art_method-inl.h"
+#include "art_method-inl.h"
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
-#include "utils.h"
 
 namespace art {
 namespace arm64 {
@@ -28,12 +28,8 @@
 static constexpr uint64_t gZero = 0;
 
 void Arm64Context::Reset() {
-  for (size_t i = 0; i < kNumberOfXRegisters; i++) {
-    gprs_[i] = nullptr;
-  }
-  for (size_t i = 0; i < kNumberOfDRegisters; i++) {
-    fprs_[i] = nullptr;
-  }
+  std::fill_n(gprs_, arraysize(gprs_), nullptr);
+  std::fill_n(fprs_, arraysize(fprs_), nullptr);
   gprs_[SP] = &sp_;
   gprs_[LR] = &pc_;
   // Initialize registers with easy to spot debug values.
@@ -42,32 +38,23 @@
 }
 
 void Arm64Context::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
-  size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
-  size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
-  if (spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context.
-    int j = 1;
-    for (size_t i = 0; i < kNumberOfXRegisters; i++) {
-      if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
-        gprs_[i] = fr.CalleeSaveAddress(spill_count  - j, frame_info.FrameSizeInBytes());
-        j++;
-      }
-    }
-  }
+  int spill_pos = 0;
 
-  if (fp_spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context.
-    int j = 1;
-    for (size_t i = 0; i < kNumberOfDRegisters; i++) {
-      if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
-        fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
-                                        frame_info.FrameSizeInBytes());
-        j++;
-      }
-    }
+  // Core registers come first, from the highest down to the lowest.
+  for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask())) {
+    gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+    ++spill_pos;
   }
+  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
+
+  // FP registers come second, from the highest down to the lowest.
+  for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
+    fprs_[fp_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+    ++spill_pos;
+  }
+  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
 }
 
 void Arm64Context::SetGPR(uint32_t reg, uintptr_t value) {
@@ -103,6 +90,7 @@
   gprs_[X13] = nullptr;
   gprs_[X14] = nullptr;
   gprs_[X15] = nullptr;
+  gprs_[X18] = nullptr;
 
   // d0-d7, d16-d31 are caller-saved; d8-d15 are callee-saved.
 
@@ -146,7 +134,7 @@
     gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : Arm64Context::kBadGprBase + i;
   }
   for (size_t i = 0; i < kNumberOfDRegisters; ++i) {
-    fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : Arm64Context::kBadGprBase + i;
+    fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : Arm64Context::kBadFprBase + i;
   }
   DCHECK_EQ(reinterpret_cast<uintptr_t>(Thread::Current()), gprs[TR]);
   art_quick_do_long_jump(gprs, fprs);
diff --git a/runtime/arch/arm64/entrypoints_init_arm64.cc b/runtime/arch/arm64/entrypoints_init_arm64.cc
index 8c8f8d5..2ce2a29 100644
--- a/runtime/arch/arm64/entrypoints_init_arm64.cc
+++ b/runtime/arch/arm64/entrypoints_init_arm64.cc
@@ -27,16 +27,9 @@
 namespace art {
 
 // Cast entrypoints.
-extern "C" uint32_t art_quick_assignable_from_code(const mirror::Class* klass,
+extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass,
                                             const mirror::Class* ref_class);
 
-// Single-precision FP arithmetics.
-extern "C" float art_quick_fmodf(float a, float b);          // REM_FLOAT[_2ADDR]
-
-// Double-precision FP arithmetics.
-extern "C" double art_quick_fmod(double a, double b);        // REM_DOUBLE[_2ADDR]
-
-
 void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
                      QuickEntryPoints* qpoints) {
   // Interpreter
@@ -50,7 +43,7 @@
   ResetQuickAllocEntryPoints(qpoints);
 
   // Cast
-  qpoints->pInstanceofNonTrivial = art_quick_assignable_from_code;
+  qpoints->pInstanceofNonTrivial = artIsAssignableFromCode;
   qpoints->pCheckCast = art_quick_check_cast;
 
   // DexCache
@@ -110,9 +103,9 @@
   qpoints->pCmpgFloat = nullptr;
   qpoints->pCmplDouble = nullptr;
   qpoints->pCmplFloat = nullptr;
-  qpoints->pFmod = art_quick_fmod;
+  qpoints->pFmod = fmod;
   qpoints->pL2d = nullptr;
-  qpoints->pFmodf = art_quick_fmodf;
+  qpoints->pFmodf = fmodf;
   qpoints->pL2f = nullptr;
   qpoints->pD2iz = nullptr;
   qpoints->pF2iz = nullptr;
@@ -129,7 +122,7 @@
   // Intrinsics
   qpoints->pIndexOf = art_quick_indexof;
   qpoints->pStringCompareTo = art_quick_string_compareto;
-  qpoints->pMemcpy = art_quick_memcpy;
+  qpoints->pMemcpy = memcpy;
 
   // Invocation
   qpoints->pQuickImtConflictTrampoline = art_quick_imt_conflict_trampoline;
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 6b16a2e5..790158e 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -32,7 +32,9 @@
 
     // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
     THIS_LOAD_REQUIRES_READ_BARRIER
-    ldr wIP0, [xIP0, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET ]
+
+    // Loads appropriate callee-save-method.
+    ldr xIP0, [xIP0, RUNTIME_SAVE_ALL_CALLEE_SAVE_FRAME_OFFSET ]
 
     sub sp, sp, #176
     .cfi_adjust_cfa_offset 176
@@ -42,43 +44,40 @@
 #error "SAVE_ALL_CALLEE_SAVE_FRAME(ARM64) size not as expected."
 #endif
 
-    // FP callee-saves
-    stp d8, d9,   [sp, #8]
-    stp d10, d11, [sp, #24]
-    stp d12, d13, [sp, #40]
-    stp d14, d15, [sp, #56]
+    // Stack alignment filler [sp, #8].
+    // FP callee-saves.
+    stp d8, d9,   [sp, #16]
+    stp d10, d11, [sp, #32]
+    stp d12, d13, [sp, #48]
+    stp d14, d15, [sp, #64]
 
-    // Thread register and x19 (callee-save)
-    stp xSELF, x19, [sp, #72]
-    .cfi_rel_offset x18, 72
+    // GP callee-saves
+    stp x19, x20, [sp, #80]
     .cfi_rel_offset x19, 80
-
-    // callee-saves
-    stp x20, x21, [sp, #88]
     .cfi_rel_offset x20, 88
+
+    stp x21, x22, [sp, #96]
     .cfi_rel_offset x21, 96
-
-    stp x22, x23, [sp, #104]
     .cfi_rel_offset x22, 104
+
+    stp x23, x24, [sp, #112]
     .cfi_rel_offset x23, 112
-
-    stp x24, x25, [sp, #120]
     .cfi_rel_offset x24, 120
+
+    stp x25, x26, [sp, #128]
     .cfi_rel_offset x25, 128
-
-    stp x26, x27, [sp, #136]
     .cfi_rel_offset x26, 136
+
+    stp x27, x28, [sp, #144]
     .cfi_rel_offset x27, 144
-
-    stp x28, x29, [sp, #152]
     .cfi_rel_offset x28, 152
-    .cfi_rel_offset x29, 160
 
-    str xLR, [sp, #168]
+    stp x29, xLR, [sp, #160]
+    .cfi_rel_offset x29, 160
     .cfi_rel_offset x30, 168
 
-    // Loads appropriate callee-save-method
-    str xIP0, [sp]    // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs]
+    // Store ArtMethod* Runtime::callee_save_methods_[kRefsAndArgs].
+    str xIP0, [sp]
     // Place sp in Thread::Current()->top_quick_frame.
     mov xIP0, sp
     str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
@@ -95,49 +94,46 @@
     // Our registers aren't intermixed - just spill in order.
     ldr xIP0, [xIP0]  // xIP0 = & (art::Runtime * art::Runtime.instance_) .
 
-    // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefAndArgs]  .
+    // xIP0 = (ArtMethod*) Runtime.instance_.callee_save_methods[kRefOnly]  .
     THIS_LOAD_REQUIRES_READ_BARRIER
-    ldr wIP0, [xIP0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET ]
 
-    sub sp, sp, #112
-    .cfi_adjust_cfa_offset 112
+    // Loads appropriate callee-save-method.
+    ldr xIP0, [xIP0, RUNTIME_REFS_ONLY_CALLEE_SAVE_FRAME_OFFSET ]
+
+    sub sp, sp, #96
+    .cfi_adjust_cfa_offset 96
 
     // Ugly compile-time check, but we only have the preprocessor.
-#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 112)
+#if (FRAME_SIZE_REFS_ONLY_CALLEE_SAVE != 96)
 #error "REFS_ONLY_CALLEE_SAVE_FRAME(ARM64) size not as expected."
 #endif
 
-    // Callee-saves
-    stp x19, x20,  [sp, #16]
-    .cfi_rel_offset x19, 16
-    .cfi_rel_offset x20, 24
+    // GP callee-saves.
+    // x20 paired with ArtMethod* - see below.
+    stp x21, x22, [sp, #16]
+    .cfi_rel_offset x21, 16
+    .cfi_rel_offset x22, 24
 
-    stp x21, x22, [sp, #32]
-    .cfi_rel_offset x21, 32
-    .cfi_rel_offset x22, 40
+    stp x23, x24, [sp, #32]
+    .cfi_rel_offset x23, 32
+    .cfi_rel_offset x24, 40
 
-    stp x23, x24, [sp, #48]
-    .cfi_rel_offset x23, 48
-    .cfi_rel_offset x24, 56
+    stp x25, x26, [sp, #48]
+    .cfi_rel_offset x25, 48
+    .cfi_rel_offset x26, 56
 
-    stp x25, x26, [sp, #64]
-    .cfi_rel_offset x25, 64
-    .cfi_rel_offset x26, 72
+    stp x27, x28, [sp, #64]
+    .cfi_rel_offset x27, 64
+    .cfi_rel_offset x28, 72
 
-    stp x27, x28, [sp, #80]
-    .cfi_rel_offset x27, 80
-    .cfi_rel_offset x28, 88
+    stp x29, xLR, [sp, #80]
+    .cfi_rel_offset x29, 80
+    .cfi_rel_offset x30, 88
 
-    // x29(callee-save) and LR
-    stp x29, xLR, [sp, #96]
-    .cfi_rel_offset x29, 96
-    .cfi_rel_offset x30, 104
+    // Store ArtMethod* Runtime::callee_save_methods_[kRefsOnly].
+    stp xIP0, x20, [sp]
+    .cfi_rel_offset x20, 8
 
-    // Save xSELF to xETR.
-    mov xETR, xSELF
-
-    // Loads appropriate callee-save-method
-    str xIP0, [sp]    // Store ArtMethod* Runtime::callee_save_methods_[kRefsOnly]
     // Place sp in Thread::Current()->top_quick_frame.
     mov xIP0, sp
     str xIP0, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
@@ -145,48 +141,37 @@
 
 // TODO: Probably no need to restore registers preserved by aapcs64.
 .macro RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME
-    // Restore xSELF.
-    mov xSELF, xETR
-
-    // Callee-saves
-    ldp x19, x20,  [sp, #16]
-    .cfi_restore x19
+    // Callee-saves.
+    ldr x20, [sp, #8]
     .cfi_restore x20
 
-    ldp x21, x22, [sp, #32]
+    ldp x21, x22, [sp, #16]
     .cfi_restore x21
     .cfi_restore x22
 
-    ldp x23, x24, [sp, #48]
+    ldp x23, x24, [sp, #32]
     .cfi_restore x23
     .cfi_restore x24
 
-    ldp x25, x26, [sp, #64]
+    ldp x25, x26, [sp, #48]
     .cfi_restore x25
     .cfi_restore x26
 
-    ldp x27, x28, [sp, #80]
+    ldp x27, x28, [sp, #64]
     .cfi_restore x27
     .cfi_restore x28
 
-    // x29(callee-save) and LR
-    ldp x29, xLR, [sp, #96]
+    ldp x29, xLR, [sp, #80]
     .cfi_restore x29
     .cfi_restore x30
 
-    add sp, sp, #112
-    .cfi_adjust_cfa_offset -112
+    add sp, sp, #96
+    .cfi_adjust_cfa_offset -96
 .endm
 
 .macro POP_REFS_ONLY_CALLEE_SAVE_FRAME
-    // Restore xSELF as it might be scratched.
-    mov xSELF, xETR
-    // ETR
-    ldr xETR, [sp, #32]
-    .cfi_restore x21
-
-    add sp, sp, #112
-    .cfi_adjust_cfa_offset -112
+    add sp, sp, #96
+    .cfi_adjust_cfa_offset - 96
 .endm
 
 .macro RESTORE_REFS_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
@@ -204,31 +189,29 @@
 #error "REFS_AND_ARGS_CALLEE_SAVE_FRAME(ARM64) size not as expected."
 #endif
 
+    // Stack alignment filler [sp, #8].
     // FP args.
-    stp d0, d1, [sp, #8]
-    stp d2, d3, [sp, #24]
-    stp d4, d5, [sp, #40]
-    stp d6, d7, [sp, #56]
+    stp d0, d1, [sp, #16]
+    stp d2, d3, [sp, #32]
+    stp d4, d5, [sp, #48]
+    stp d6, d7, [sp, #64]
 
     // Core args.
-    str x1, [sp, 72]
-    .cfi_rel_offset x1, 72
+    stp x1, x2, [sp, #80]
+    .cfi_rel_offset x1, 80
+    .cfi_rel_offset x2, 88
 
-    stp x2,  x3, [sp, #80]
-    .cfi_rel_offset x2, 80
-    .cfi_rel_offset x3, 88
+    stp x3, x4, [sp, #96]
+    .cfi_rel_offset x3, 96
+    .cfi_rel_offset x4, 104
 
-    stp x4,  x5, [sp, #96]
-    .cfi_rel_offset x4, 96
-    .cfi_rel_offset x5, 104
+    stp x5, x6, [sp, #112]
+    .cfi_rel_offset x5, 112
+    .cfi_rel_offset x6, 120
 
-    stp x6,  x7, [sp, #112]
-    .cfi_rel_offset x6, 112
-    .cfi_rel_offset x7, 120
-
-    // Callee-saves.
-    stp x19, x20, [sp, #128]
-    .cfi_rel_offset x19, 128
+    // x7, Callee-saves.
+    stp x7, x20, [sp, #128]
+    .cfi_rel_offset x7, 128
     .cfi_rel_offset x20, 136
 
     stp x21, x22, [sp, #144]
@@ -247,13 +230,11 @@
     .cfi_rel_offset x27, 192
     .cfi_rel_offset x28, 200
 
-    // x29(callee-save) and LR
+    // x29(callee-save) and LR.
     stp x29, xLR, [sp, #208]
     .cfi_rel_offset x29, 208
     .cfi_rel_offset x30, 216
 
-    // Save xSELF to xETR.
-    mov xETR, xSELF
 .endm
 
     /*
@@ -271,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
 
@@ -291,34 +272,28 @@
 
 // TODO: Probably no need to restore registers preserved by aapcs64.
 .macro RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME
-    // Restore xSELF.
-    mov xSELF, xETR
-
     // FP args.
-    ldp d0, d1, [sp, #8]
-    ldp d2, d3, [sp, #24]
-    ldp d4, d5, [sp, #40]
-    ldp d6, d7, [sp, #56]
+    ldp d0, d1, [sp, #16]
+    ldp d2, d3, [sp, #32]
+    ldp d4, d5, [sp, #48]
+    ldp d6, d7, [sp, #64]
 
     // Core args.
-    ldr x1, [sp, 72]
+    ldp x1, x2, [sp, #80]
     .cfi_restore x1
-
-    ldp x2,  x3, [sp, #80]
     .cfi_restore x2
+
+    ldp x3, x4, [sp, #96]
     .cfi_restore x3
-
-    ldp x4,  x5, [sp, #96]
     .cfi_restore x4
+
+    ldp x5, x6, [sp, #112]
     .cfi_restore x5
-
-    ldp x6,  x7, [sp, #112]
     .cfi_restore x6
-    .cfi_restore x7
 
-    // Callee-saves.
-    ldp x19, x20, [sp, #128]
-    .cfi_restore x19
+    // x7, Callee-saves.
+    ldp x7, x20, [sp, #128]
+    .cfi_restore x7
     .cfi_restore x20
 
     ldp x21, x22, [sp, #144]
@@ -337,7 +312,7 @@
     .cfi_restore x27
     .cfi_restore x28
 
-    // x29(callee-save) and LR
+    // x29(callee-save) and LR.
     ldp x29, xLR, [sp, #208]
     .cfi_restore x29
     .cfi_restore x30
@@ -506,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.
 
@@ -563,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\@:
@@ -577,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
 
@@ -679,7 +650,7 @@
  *  | uint32_t out[n-1]    |
  *  |    :      :          |        Outs
  *  | uint32_t out[0]      |
- *  | StackRef<ArtMethod>  | <- SP  value=null
+ *  | ArtMethod*           | <- SP  value=null
  *  +----------------------+
  *
  * Outgoing registers:
@@ -1106,13 +1077,12 @@
     .extern artThrowClassCastException
 ENTRY art_quick_check_cast
     // Store arguments and link register
-    sub sp, sp, #32                     // Stack needs to be 16b aligned on calls
+    // Stack needs to be 16B aligned on calls.
+    stp x0, x1, [sp,#-32]!
     .cfi_adjust_cfa_offset 32
-    stp x0, x1, [sp]
     .cfi_rel_offset x0, 0
     .cfi_rel_offset x1, 8
-    stp xSELF, xLR, [sp, #16]
-    .cfi_rel_offset x18, 16
+    str xLR, [sp, #24]
     .cfi_rel_offset x30, 24
 
     // Call runtime code
@@ -1122,25 +1092,21 @@
     cbz x0, .Lthrow_class_cast_exception
 
     // Restore and return
-    ldp x0, x1, [sp]
+    ldr xLR, [sp, #24]
+    .cfi_restore x30
+    ldp x0, x1, [sp], #32
     .cfi_restore x0
     .cfi_restore x1
-    ldp xSELF, xLR, [sp, #16]
-    .cfi_restore x18
-    .cfi_restore x30
-    add sp, sp, #32
     .cfi_adjust_cfa_offset -32
     ret
 
 .Lthrow_class_cast_exception:
     // Restore
-    ldp x0, x1, [sp]
+    ldr xLR, [sp, #24]
+    .cfi_restore x30
+    ldp x0, x1, [sp], #32
     .cfi_restore x0
     .cfi_restore x1
-    ldp xSELF, xLR, [sp, #16]
-    .cfi_restore x18
-    .cfi_restore x30
-    add sp, sp, #32
     .cfi_adjust_cfa_offset -32
 
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
@@ -1201,16 +1167,13 @@
     ret
 .Lcheck_assignability:
     // Store arguments and link register
-    sub sp, sp, #48                     // Stack needs to be 16b aligned on calls
-    .cfi_adjust_cfa_offset 48
-    stp x0, x1, [sp]
+    stp x0, x1, [sp,#-32]!
+    .cfi_adjust_cfa_offset 32
     .cfi_rel_offset x0, 0
     .cfi_rel_offset x1, 8
-    stp x2, xSELF, [sp, #16]
+    stp x2, xLR, [sp, #16]
     .cfi_rel_offset x2, 16
-    .cfi_rel_offset x18, 24
-    str xLR, [sp, #32]
-    .cfi_rel_offset x30, 32
+    .cfi_rel_offset x30, 24
 
     // Call runtime code
     mov x0, x3              // Heap reference, 32b, "uncompress" = do nothing, already zero-extended
@@ -1221,16 +1184,13 @@
     cbz x0, .Lthrow_array_store_exception
 
     // Restore
-    ldp x0, x1, [sp]
+    ldp x2, x30, [sp, #16]
+    .cfi_restore x2
+    .cfi_restore x30
+    ldp x0, x1, [sp], #32
     .cfi_restore x0
     .cfi_restore x1
-    ldp x2, xSELF, [sp, #16]
-    .cfi_restore x2
-    .cfi_restore x18
-    ldr xLR, [sp, #32]
-    .cfi_restore x30
-    add sp, sp, #48
-    .cfi_adjust_cfa_offset -48
+    .cfi_adjust_cfa_offset -32
 
     add x3, x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET
                                                           // "Compress" = do nothing
@@ -1240,16 +1200,13 @@
     strb w3, [x3, x0]
     ret
 .Lthrow_array_store_exception:
-    ldp x0, x1, [sp]
+    ldp x2, x30, [sp, #16]
+    .cfi_restore x2
+    .cfi_restore x30
+    ldp x0, x1, [sp], #32
     .cfi_restore x0
     .cfi_restore x1
-    ldp x2, xSELF, [sp, #16]
-    .cfi_restore x2
-    .cfi_restore x18
-    ldr xLR, [sp, #32]
-    .cfi_restore x30
-    add sp, sp, #48
-    .cfi_adjust_cfa_offset -48
+    .cfi_adjust_cfa_offset -32
 
     SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     mov x1, x2                    // Pass value.
@@ -1312,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
@@ -1324,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
@@ -1336,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
@@ -1399,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
@@ -1450,8 +1407,7 @@
     mov     x2, xSELF                   // pass Thread::Current
     mov     x3, sp                      // pass SP
     bl      artQuickProxyInvokeHandler  // (Method* proxy method, receiver, Thread*, SP)
-    // Use xETR as xSELF might be scratched by native function above.
-    ldr     x2, [xETR, THREAD_EXCEPTION_OFFSET]
+    ldr     x2, [xSELF, THREAD_EXCEPTION_OFFSET]
     cbnz    x2, .Lexception_in_proxy    // success if no exception is pending
     RESTORE_REFS_AND_ARGS_CALLEE_SAVE_FRAME // Restore frame
     fmov    d0, x0                      // Store result in d0 in case it was float or double
@@ -1466,10 +1422,7 @@
      * dex method index.
      */
 ENTRY art_quick_imt_conflict_trampoline
-    ldr    w0, [sp, #0]                                // load caller Method*
-    ldr    w0, [x0, #MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET]  // load dex_cache_resolved_methods
-    add    x0, x0, #MIRROR_OBJECT_ARRAY_DATA_OFFSET    // get starting address of data
-    ldr    w0, [x0, xIP1, lsl 2]                       // load the target method
+    mov    x0, xIP1
     b art_quick_invoke_interface_trampoline
 END art_quick_imt_conflict_trampoline
 
@@ -1480,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:
@@ -1601,15 +1554,14 @@
     // prepare for artQuickGenericJniEndTrampoline call
     // (Thread*, result, result_f)
     //    x0       x1       x2        <= C calling convention
-    mov x1, x0      // Result (from saved)
-    mov x0, xETR    // Thread register, original xSELF might be scratched by native code.
+    mov x1, x0      // Result (from saved).
+    mov x0, xSELF   // Thread register.
     fmov x2, d0     // d0 will contain floating point result, but needs to go into x2
 
     bl artQuickGenericJniEndTrampoline
 
     // Pending exceptions possible.
-    // Use xETR as xSELF might be scratched by native code
-    ldr x2, [xETR, THREAD_EXCEPTION_OFFSET]
+    ldr x2, [xSELF, THREAD_EXCEPTION_OFFSET]
     cbnz x2, .Lexception_in_native
 
     // Tear down the alloca.
@@ -1624,8 +1576,6 @@
     ret
 
 .Lexception_in_native:
-    // Restore xSELF. It might have been scratched by native code.
-    mov xSELF, xETR
     // Move to x1 then sp to please assembler.
     ldr x1, [xSELF, # THREAD_TOP_QUICK_FRAME_OFFSET]
     mov sp, x1
@@ -1921,21 +1871,3 @@
     csel x0, x0, x14, ne         // x0 := x0 != 0 ? x14(prev x0=length diff) : x1.
     ret
 END art_quick_string_compareto
-
-// Macro to facilitate adding new entrypoints which call to native function directly.
-// Currently, xSELF is the only thing we need to take care of between managed code and AAPCS.
-// But we might introduce more differences.
-.macro NATIVE_DOWNCALL name, entrypoint
-    .extern \entrypoint
-ENTRY \name
-    stp    xSELF, xLR, [sp, #-16]!
-    bl     \entrypoint
-    ldp    xSELF, xLR, [sp], #16
-    ret
-END \name
-.endm
-
-NATIVE_DOWNCALL art_quick_fmod fmod
-NATIVE_DOWNCALL art_quick_fmodf fmodf
-NATIVE_DOWNCALL art_quick_memcpy memcpy
-NATIVE_DOWNCALL art_quick_assignable_from_code artIsAssignableFromCode
diff --git a/runtime/arch/arm64/quick_method_frame_info_arm64.h b/runtime/arch/arm64/quick_method_frame_info_arm64.h
index 61b4dff..b525309 100644
--- a/runtime/arch/arm64/quick_method_frame_info_arm64.h
+++ b/runtime/arch/arm64/quick_method_frame_info_arm64.h
@@ -17,10 +17,10 @@
 #ifndef ART_RUNTIME_ARCH_ARM64_QUICK_METHOD_FRAME_INFO_ARM64_H_
 #define ART_RUNTIME_ARCH_ARM64_QUICK_METHOD_FRAME_INFO_ARM64_H_
 
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_arm64.h"
 #include "runtime.h"  // for Runtime::CalleeSaveType.
-#include "utils.h"  // for POPCOUNT
 
 namespace art {
 namespace arm64 {
@@ -33,18 +33,17 @@
     (1 << art::arm64::LR);
 // Callee saved registers
 static constexpr uint32_t kArm64CalleeSaveRefSpills =
-    (1 << art::arm64::X19) | (1 << art::arm64::X20) | (1 << art::arm64::X21) |
-    (1 << art::arm64::X22) | (1 << art::arm64::X23) | (1 << art::arm64::X24) |
-    (1 << art::arm64::X25) | (1 << art::arm64::X26) | (1 << art::arm64::X27) |
-    (1 << art::arm64::X28) | (1 << art::arm64::X29);
+    (1 << art::arm64::X20) | (1 << art::arm64::X21) | (1 << art::arm64::X22) |
+    (1 << art::arm64::X23) | (1 << art::arm64::X24) | (1 << art::arm64::X25) |
+    (1 << art::arm64::X26) | (1 << art::arm64::X27) | (1 << art::arm64::X28) |
+    (1 << art::arm64::X29);
 // X0 is the method pointer. Not saved.
 static constexpr uint32_t kArm64CalleeSaveArgSpills =
     (1 << art::arm64::X1) | (1 << art::arm64::X2) | (1 << art::arm64::X3) |
     (1 << art::arm64::X4) | (1 << art::arm64::X5) | (1 << art::arm64::X6) |
     (1 << art::arm64::X7);
 static constexpr uint32_t kArm64CalleeSaveAllSpills =
-    // Thread register.
-    (1 << art::arm64::X18);
+    (1 << art::arm64::X19);
 
 static constexpr uint32_t kArm64CalleeSaveFpAlwaysSpills = 0;
 static constexpr uint32_t kArm64CalleeSaveFpRefSpills = 0;
diff --git a/runtime/arch/arm64/registers_arm64.h b/runtime/arch/arm64/registers_arm64.h
index 51ae184..4683fc3 100644
--- a/runtime/arch/arm64/registers_arm64.h
+++ b/runtime/arch/arm64/registers_arm64.h
@@ -60,8 +60,7 @@
                  // different enum value to distinguish between the two.
   kNumberOfXRegisters = 33,
   // Aliases.
-  TR  = X18,     // ART Thread Register - Managed Runtime (Caller Saved Reg)
-  ETR = X21,     // ART Thread Register - External Calls  (Callee Saved Reg)
+  TR  = X19,     // ART Thread Register - Managed Runtime (Callee Saved Reg)
   IP0 = X16,     // Used as scratch by VIXL.
   IP1 = X17,     // Used as scratch by ART JNI Assembler.
   FP  = X29,
diff --git a/runtime/arch/memcmp16_test.cc b/runtime/arch/memcmp16_test.cc
index 5ba06f8..9ba7de1 100644
--- a/runtime/arch/memcmp16_test.cc
+++ b/runtime/arch/memcmp16_test.cc
@@ -144,10 +144,10 @@
     ASSERT_EQ(expected, computed) << "Run " << round << ", c1=" << count1 << " c2=" << count2;
 
     if (count1 > 0U) {
-      delete s1;
+      delete[] s1;
     }
     if (count2 > 0U) {
-      delete s2;
+      delete[] s2;
     }
   }
 }
diff --git a/runtime/arch/mips/asm_support_mips.h b/runtime/arch/mips/asm_support_mips.h
index 02c0982..390c606 100644
--- a/runtime/arch/mips/asm_support_mips.h
+++ b/runtime/arch/mips/asm_support_mips.h
@@ -19,7 +19,7 @@
 
 #include "asm_support.h"
 
-#define FRAME_SIZE_SAVE_ALL_CALLEE_SAVE 48
+#define FRAME_SIZE_SAVE_ALL_CALLEE_SAVE 96
 #define FRAME_SIZE_REFS_ONLY_CALLEE_SAVE 48
 #define FRAME_SIZE_REFS_AND_ARGS_CALLEE_SAVE 64
 
diff --git a/runtime/arch/mips/context_mips.cc b/runtime/arch/mips/context_mips.cc
index 3b525be..53f2b65 100644
--- a/runtime/arch/mips/context_mips.cc
+++ b/runtime/arch/mips/context_mips.cc
@@ -16,9 +16,9 @@
 
 #include "context_mips.h"
 
-#include "mirror/art_method-inl.h"
+#include "art_method-inl.h"
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
-#include "utils.h"
 
 namespace art {
 namespace mips {
@@ -26,12 +26,8 @@
 static constexpr uint32_t gZero = 0;
 
 void MipsContext::Reset() {
-  for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
-    gprs_[i] = nullptr;
-  }
-  for (size_t i = 0; i < kNumberOfFRegisters; i++) {
-    fprs_[i] = nullptr;
-  }
+  std::fill_n(gprs_, arraysize(gprs_), nullptr);
+  std::fill_n(fprs_, arraysize(fprs_), nullptr);
   gprs_[SP] = &sp_;
   gprs_[RA] = &ra_;
   // Initialize registers with easy to spot debug values.
@@ -40,31 +36,23 @@
 }
 
 void MipsContext::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
-  size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
-  size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
-  if (spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context.
-    int j = 1;
-    for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
-      if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
-        gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
-        j++;
-      }
-    }
+  int spill_pos = 0;
+
+  // Core registers come first, from the highest down to the lowest.
+  for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask())) {
+    gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+    ++spill_pos;
   }
-  if (fp_spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context.
-    int j = 1;
-    for (size_t i = 0; i < kNumberOfFRegisters; i++) {
-      if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
-        fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
-                                        frame_info.FrameSizeInBytes());
-        j++;
-      }
-    }
+  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
+
+  // FP registers come second, from the highest down to the lowest.
+  for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
+    fprs_[fp_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+    ++spill_pos;
   }
+  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
 }
 
 void MipsContext::SetGPR(uint32_t reg, uintptr_t value) {
@@ -99,7 +87,7 @@
     gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : MipsContext::kBadGprBase + i;
   }
   for (size_t i = 0; i < kNumberOfFRegisters; ++i) {
-    fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : MipsContext::kBadGprBase + i;
+    fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : MipsContext::kBadFprBase + i;
   }
   art_quick_do_long_jump(gprs, fprs);
 }
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 92b180e..9e1dab6 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -37,36 +37,44 @@
      * Reserves FRAME_SIZE_SAVE_ALL_CALLEE_SAVE + ARG_SLOT_SIZE bytes on the stack
      */
 .macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
-    addiu  $sp, $sp, -48
-    .cfi_adjust_cfa_offset 48
+    addiu  $sp, $sp, -96
+    .cfi_adjust_cfa_offset 96
 
      // Ugly compile-time check, but we only have the preprocessor.
-#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 48)
+#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVE != 96)
 #error "SAVE_ALL_CALLEE_SAVE_FRAME(MIPS) size not as expected."
 #endif
 
-    sw     $ra, 44($sp)
-    .cfi_rel_offset 31, 44
-    sw     $s8, 40($sp)
-    .cfi_rel_offset 30, 40
-    sw     $gp, 36($sp)
-    .cfi_rel_offset 28, 36
-    sw     $s7, 32($sp)
-    .cfi_rel_offset 23, 32
-    sw     $s6, 28($sp)
-    .cfi_rel_offset 22, 28
-    sw     $s5, 24($sp)
-    .cfi_rel_offset 21, 24
-    sw     $s4, 20($sp)
-    .cfi_rel_offset 20, 20
-    sw     $s3, 16($sp)
-    .cfi_rel_offset 19, 16
-    sw     $s2, 12($sp)
-    .cfi_rel_offset 18, 12
-    sw     $s1, 8($sp)
-    .cfi_rel_offset 17, 8
-    sw     $s0, 4($sp)
-    .cfi_rel_offset 16, 4
+    sw     $ra, 92($sp)
+    .cfi_rel_offset 31, 92
+    sw     $s8, 88($sp)
+    .cfi_rel_offset 30, 88
+    sw     $gp, 84($sp)
+    .cfi_rel_offset 28, 84
+    sw     $s7, 80($sp)
+    .cfi_rel_offset 23, 80
+    sw     $s6, 76($sp)
+    .cfi_rel_offset 22, 76
+    sw     $s5, 72($sp)
+    .cfi_rel_offset 21, 72
+    sw     $s4, 68($sp)
+    .cfi_rel_offset 20, 68
+    sw     $s3, 64($sp)
+    .cfi_rel_offset 19, 64
+    sw     $s2, 60($sp)
+    .cfi_rel_offset 18, 60
+    sw     $s1, 56($sp)
+    .cfi_rel_offset 17, 56
+    sw     $s0, 52($sp)
+    .cfi_rel_offset 16, 52
+
+    SDu $f30, $f31, 44, $sp, $t1
+    SDu $f28, $f29, 36, $sp, $t1
+    SDu $f26, $f27, 28, $sp, $t1
+    SDu $f24, $f25, 20, $sp, $t1
+    SDu $f22, $f23, 12, $sp, $t1
+    SDu $f20, $f21, 4,  $sp, $t1
+
     # 1 word for holding Method*
 
     lw $t0, %got(_ZN3art7Runtime9instance_E)($gp)
@@ -515,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
@@ -1091,13 +1099,9 @@
      * dex method index.
      */
 ENTRY art_quick_imt_conflict_trampoline
-    lw      $a0, 0($sp)            # load caller Method*
-    lw      $a0, MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET($a0)  # load dex_cache_resolved_methods
-    sll     $t0, 2                 # convert target method offset to bytes
-    add     $a0, $t0               # get address of target method
-    lw      $a0, MIRROR_OBJECT_ARRAY_DATA_OFFSET($a0)  # load the target method
     la      $t9, art_quick_invoke_interface_trampoline
     jalr    $zero, $t9
+    move    $a0, $t0
 END art_quick_imt_conflict_trampoline
 
     .extern artQuickResolutionTrampoline
diff --git a/runtime/arch/mips/quick_method_frame_info_mips.h b/runtime/arch/mips/quick_method_frame_info_mips.h
index 5fbffbc..dd5ac80 100644
--- a/runtime/arch/mips/quick_method_frame_info_mips.h
+++ b/runtime/arch/mips/quick_method_frame_info_mips.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_ARCH_MIPS_QUICK_METHOD_FRAME_INFO_MIPS_H_
 #define ART_RUNTIME_ARCH_MIPS_QUICK_METHOD_FRAME_INFO_MIPS_H_
 
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_mips.h"
 #include "runtime.h"  // for Runtime::CalleeSaveType.
@@ -31,6 +32,10 @@
     (1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3);
 static constexpr uint32_t kMipsCalleeSaveAllSpills =
     (1 << art::mips::S0) | (1 << art::mips::S1);
+static constexpr uint32_t kMipsCalleeSaveAllFPSpills =
+    (1 << art::mips::F20) | (1 << art::mips::F21) | (1 << art::mips::F22) | (1 << art::mips::F23) |
+    (1 << art::mips::F24) | (1 << art::mips::F25) | (1 << art::mips::F26) | (1 << art::mips::F27) |
+    (1 << art::mips::F28) | (1 << art::mips::F29) | (1 << art::mips::F30) | (1 << art::mips::F31);
 
 constexpr uint32_t MipsCalleeSaveCoreSpills(Runtime::CalleeSaveType type) {
   return kMipsCalleeSaveRefSpills |
@@ -38,15 +43,20 @@
       (type == Runtime::kSaveAll ? kMipsCalleeSaveAllSpills : 0) | (1 << art::mips::RA);
 }
 
+constexpr uint32_t MipsCalleeSaveFPSpills(Runtime::CalleeSaveType type) {
+  return type == Runtime::kSaveAll ? kMipsCalleeSaveAllFPSpills : 0;
+}
+
 constexpr uint32_t MipsCalleeSaveFrameSize(Runtime::CalleeSaveType type) {
   return RoundUp((POPCOUNT(MipsCalleeSaveCoreSpills(type)) /* gprs */ +
+                  POPCOUNT(MipsCalleeSaveFPSpills(type))   /* fprs */ +
                   1 /* Method* */) * kMipsPointerSize, kStackAlignment);
 }
 
 constexpr QuickMethodFrameInfo MipsCalleeSaveMethodFrameInfo(Runtime::CalleeSaveType type) {
   return QuickMethodFrameInfo(MipsCalleeSaveFrameSize(type),
                               MipsCalleeSaveCoreSpills(type),
-                              0u);
+                              MipsCalleeSaveFPSpills(type));
 }
 
 }  // namespace mips
diff --git a/runtime/arch/mips64/context_mips64.cc b/runtime/arch/mips64/context_mips64.cc
index 6b3f4c9..6637c37 100644
--- a/runtime/arch/mips64/context_mips64.cc
+++ b/runtime/arch/mips64/context_mips64.cc
@@ -16,9 +16,9 @@
 
 #include "context_mips64.h"
 
-#include "mirror/art_method-inl.h"
+#include "art_method-inl.h"
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
-#include "utils.h"
 
 namespace art {
 namespace mips64 {
@@ -26,12 +26,8 @@
 static constexpr uintptr_t gZero = 0;
 
 void Mips64Context::Reset() {
-  for (size_t i = 0; i < kNumberOfGpuRegisters; i++) {
-    gprs_[i] = nullptr;
-  }
-  for (size_t i = 0; i < kNumberOfFpuRegisters; i++) {
-    fprs_[i] = nullptr;
-  }
+  std::fill_n(gprs_, arraysize(gprs_), nullptr);
+  std::fill_n(fprs_, arraysize(fprs_), nullptr);
   gprs_[SP] = &sp_;
   gprs_[RA] = &ra_;
   // Initialize registers with easy to spot debug values.
@@ -40,31 +36,23 @@
 }
 
 void Mips64Context::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
-  size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
-  size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
-  if (spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context.
-    int j = 1;
-    for (size_t i = 0; i < kNumberOfGpuRegisters; i++) {
-      if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
-        gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
-        j++;
-      }
-    }
+  int spill_pos = 0;
+
+  // Core registers come first, from the highest down to the lowest.
+  for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask())) {
+    gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+    ++spill_pos;
   }
-  if (fp_spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context.
-    int j = 1;
-    for (size_t i = 0; i < kNumberOfFpuRegisters; i++) {
-      if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
-        fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
-                                        frame_info.FrameSizeInBytes());
-        j++;
-      }
-    }
+  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
+
+  // FP registers come second, from the highest down to the lowest.
+  for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
+    fprs_[fp_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+    ++spill_pos;
   }
+  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
 }
 
 void Mips64Context::SetGPR(uint32_t reg, uintptr_t value) {
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 b7320a6..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
@@ -1365,14 +1365,10 @@
      * dex method index.
      */
 ENTRY art_quick_imt_conflict_trampoline
-    lwu     $a0, 0($sp)            # load caller Method*
-    lwu     $a0, MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET($a0)  # load dex_cache_resolved_methods
-    dsll    $t0, 2                 # convert target method offset to bytes
-    daddu   $a0, $t0               # get address of target method
     dla     $t9, art_quick_invoke_interface_trampoline
     .cpreturn
     jalr    $zero, $t9
-    lwu     $a0, MIRROR_OBJECT_ARRAY_DATA_OFFSET($a0)  # load the target method
+    move    $a0, $t0
 END art_quick_imt_conflict_trampoline
 
     .extern artQuickResolutionTrampoline
@@ -1382,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/mips64/quick_method_frame_info_mips64.h b/runtime/arch/mips64/quick_method_frame_info_mips64.h
index de55e81..f967be0 100644
--- a/runtime/arch/mips64/quick_method_frame_info_mips64.h
+++ b/runtime/arch/mips64/quick_method_frame_info_mips64.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_ARCH_MIPS64_QUICK_METHOD_FRAME_INFO_MIPS64_H_
 #define ART_RUNTIME_ARCH_MIPS64_QUICK_METHOD_FRAME_INFO_MIPS64_H_
 
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_mips64.h"
 #include "runtime.h"  // for Runtime::CalleeSaveType.
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index a7d24b8..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);
@@ -173,7 +173,7 @@
         // Load call params into the right registers.
         "ldp x0, x1, [sp]\n\t"
         "ldp x2, x3, [sp, #16]\n\t"
-        "ldr x18, [sp, #32]\n\t"
+        "ldr x19, [sp, #32]\n\t"
         "add sp, sp, #48\n\t"
         ".cfi_adjust_cfa_offset -48\n\t"
 
@@ -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);
@@ -526,7 +526,7 @@
         // Load call params into the right registers.
         "ldp x0, x1, [sp]\n\t"
         "ldp x2, x3, [sp, #16]\n\t"
-        "ldp x18, x17, [sp, #32]\n\t"
+        "ldp x19, x17, [sp, #32]\n\t"
         "add sp, sp, #48\n\t"
         ".cfi_adjust_cfa_offset -48\n\t"
 
@@ -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 52a35dd..7096c82aa 100644
--- a/runtime/arch/x86/context_x86.cc
+++ b/runtime/arch/x86/context_x86.cc
@@ -16,10 +16,9 @@
 
 #include "context_x86.h"
 
-#include "mirror/art_method-inl.h"
+#include "art_method-inl.h"
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
-#include "utils.h"
-
 
 namespace art {
 namespace x86 {
@@ -27,12 +26,8 @@
 static constexpr uintptr_t gZero = 0;
 
 void X86Context::Reset() {
-  for (size_t  i = 0; i < kNumberOfCpuRegisters; i++) {
-    gprs_[i] = nullptr;
-  }
-  for (size_t i = 0; i < kNumberOfFloatRegisters; ++i) {
-    fprs_[i] = nullptr;
-  }
+  std::fill_n(gprs_, arraysize(gprs_), nullptr);
+  std::fill_n(fprs_, arraysize(fprs_), nullptr);
   gprs_[ESP] = &esp_;
   // Initialize registers with easy to spot debug values.
   esp_ = X86Context::kBadGprBase + ESP;
@@ -40,38 +35,33 @@
 }
 
 void X86Context::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
-  size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
-  size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
-  if (spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context.
-    int j = 2;  // Offset j to skip return address spill.
-    for (int i = 0; i < kNumberOfCpuRegisters; i++) {
-      if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
-        gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
-        j++;
-      }
-    }
+  int spill_pos = 0;
+
+  // Core registers come first, from the highest down to the lowest.
+  uint32_t core_regs =
+      frame_info.CoreSpillMask() & ~(static_cast<uint32_t>(-1) << kNumberOfCpuRegisters);
+  DCHECK_EQ(1, POPCOUNT(frame_info.CoreSpillMask() & ~core_regs));  // Return address spill.
+  for (uint32_t core_reg : HighToLowBits(core_regs)) {
+    gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+    ++spill_pos;
   }
-  if (fp_spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context.
-    size_t j = 2;  // Offset j to skip return address spill.
-    size_t fp_spill_size_in_words = fp_spill_count * 2;
-    for (size_t i = 0; i < kNumberOfFloatRegisters; ++i) {
-      if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
-        // There are 2 pieces to each XMM register, to match VR size.
-        fprs_[2*i] = reinterpret_cast<uint32_t*>(
-            fr.CalleeSaveAddress(spill_count + fp_spill_size_in_words - j,
-                                 frame_info.FrameSizeInBytes()));
-        fprs_[2*i+1] = reinterpret_cast<uint32_t*>(
-            fr.CalleeSaveAddress(spill_count + fp_spill_size_in_words - j - 1,
-                                 frame_info.FrameSizeInBytes()));
-        // Two void* per XMM register.
-        j += 2;
-      }
-    }
+  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) - 1);
+
+  // FP registers come second, from the highest down to the lowest.
+  uint32_t fp_regs = frame_info.FpSpillMask();
+  DCHECK_EQ(0u, fp_regs & (static_cast<uint32_t>(-1) << kNumberOfFloatRegisters));
+  for (uint32_t fp_reg : HighToLowBits(fp_regs)) {
+    // Two void* per XMM register.
+    fprs_[2 * fp_reg] = reinterpret_cast<uint32_t*>(
+        fr.CalleeSaveAddress(spill_pos + 1, frame_info.FrameSizeInBytes()));
+    fprs_[2 * fp_reg + 1] = reinterpret_cast<uint32_t*>(
+        fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes()));
+    spill_pos += 2;
   }
+  DCHECK_EQ(spill_pos,
+            POPCOUNT(frame_info.CoreSpillMask()) - 1 + 2 * POPCOUNT(frame_info.FpSpillMask()));
 }
 
 void X86Context::SmashCallerSaves() {
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 d62c1bc..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
@@ -1385,16 +1385,11 @@
 END_FUNCTION art_quick_proxy_invoke_handler
 
     /*
-     * Called to resolve an imt conflict. xmm0 is a hidden argument that holds the target method's
+     * Called to resolve an imt conflict. xmm7 is a hidden argument that holds the target method's
      * dex method index.
      */
 DEFINE_FUNCTION art_quick_imt_conflict_trampoline
-    PUSH ecx
-    movl 8(%esp), %eax            // load caller Method*
-    movl MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET(%eax), %eax  // load dex_cache_resolved_methods
-    movd %xmm7, %ecx              // get target method index stored in xmm0
-    movl MIRROR_OBJECT_ARRAY_DATA_OFFSET(%eax, %ecx, 4), %eax  // load the target method
-    POP ecx
+    movd %xmm7, %eax              // get target method index stored in xmm7
     jmp SYMBOL(art_quick_invoke_interface_trampoline)
 END_FUNCTION art_quick_imt_conflict_trampoline
 
diff --git a/runtime/arch/x86/quick_method_frame_info_x86.h b/runtime/arch/x86/quick_method_frame_info_x86.h
index 9bba531..ed1d860 100644
--- a/runtime/arch/x86/quick_method_frame_info_x86.h
+++ b/runtime/arch/x86/quick_method_frame_info_x86.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_ARCH_X86_QUICK_METHOD_FRAME_INFO_X86_H_
 #define ART_RUNTIME_ARCH_X86_QUICK_METHOD_FRAME_INFO_X86_H_
 
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_x86.h"
 #include "runtime.h"  // for Runtime::CalleeSaveType.
diff --git a/runtime/arch/x86_64/context_x86_64.cc b/runtime/arch/x86_64/context_x86_64.cc
index 6336541..1fe2ef8 100644
--- a/runtime/arch/x86_64/context_x86_64.cc
+++ b/runtime/arch/x86_64/context_x86_64.cc
@@ -16,9 +16,9 @@
 
 #include "context_x86_64.h"
 
-#include "mirror/art_method-inl.h"
+#include "art_method-inl.h"
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
-#include "utils.h"
 
 namespace art {
 namespace x86_64 {
@@ -26,12 +26,8 @@
 static constexpr uintptr_t gZero = 0;
 
 void X86_64Context::Reset() {
-  for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-    gprs_[i] = nullptr;
-  }
-  for (size_t i = 0; i < kNumberOfFloatRegisters; ++i) {
-    fprs_[i] = nullptr;
-  }
+  std::fill_n(gprs_, arraysize(gprs_), nullptr);
+  std::fill_n(fprs_, arraysize(fprs_), nullptr);
   gprs_[RSP] = &rsp_;
   // Initialize registers with easy to spot debug values.
   rsp_ = X86_64Context::kBadGprBase + RSP;
@@ -39,31 +35,30 @@
 }
 
 void X86_64Context::FillCalleeSaves(const StackVisitor& fr) {
-  mirror::ArtMethod* method = fr.GetMethod();
+  ArtMethod* method = fr.GetMethod();
   const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
-  size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
-  size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
-  if (spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context.
-    size_t j = 2;  // Offset j to skip return address spill.
-    for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) {
-      if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
-        gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
-        j++;
-      }
-    }
+  int spill_pos = 0;
+
+  // Core registers come first, from the highest down to the lowest.
+  uint32_t core_regs =
+      frame_info.CoreSpillMask() & ~(static_cast<uint32_t>(-1) << kNumberOfCpuRegisters);
+  DCHECK_EQ(1, POPCOUNT(frame_info.CoreSpillMask() & ~core_regs));  // Return address spill.
+  for (uint32_t core_reg : HighToLowBits(core_regs)) {
+    gprs_[core_reg] = fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes());
+    ++spill_pos;
   }
-  if (fp_spill_count > 0) {
-    // Lowest number spill is farthest away, walk registers and fill into context.
-    size_t j = 2;  // Offset j to skip return address spill.
-    for (size_t i = 0; i < kNumberOfFloatRegisters; ++i) {
-      if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
-        fprs_[i] = reinterpret_cast<uint64_t*>(
-            fr.CalleeSaveAddress(spill_count + fp_spill_count - j, frame_info.FrameSizeInBytes()));
-        j++;
-      }
-    }
+  DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) - 1);
+
+  // FP registers come second, from the highest down to the lowest.
+  uint32_t fp_regs = frame_info.FpSpillMask();
+  DCHECK_EQ(0u, fp_regs & (static_cast<uint32_t>(-1) << kNumberOfFloatRegisters));
+  for (uint32_t fp_reg : HighToLowBits(fp_regs)) {
+    fprs_[fp_reg] = reinterpret_cast<uint64_t*>(
+        fr.CalleeSaveAddress(spill_pos, frame_info.FrameSizeInBytes()));
+    ++spill_pos;
   }
+  DCHECK_EQ(spill_pos,
+            POPCOUNT(frame_info.CoreSpillMask()) - 1 + POPCOUNT(frame_info.FpSpillMask()));
 }
 
 void X86_64Context::SmashCallerSaves() {
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index ddeb5b8..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()
@@ -1338,9 +1336,7 @@
     int3
     int3
 #else
-    movl 8(%rsp), %edi            // load caller Method*
-    movl MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET(%rdi), %edi  // load dex_cache_resolved_methods
-    movl MIRROR_OBJECT_ARRAY_DATA_OFFSET(%rdi, %rax, 4), %edi  // load the target method
+    movq %rax, %rdi
     jmp art_quick_invoke_interface_trampoline
 #endif  // __APPLE__
 END_FUNCTION art_quick_imt_conflict_trampoline
@@ -1393,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/arch/x86_64/quick_method_frame_info_x86_64.h b/runtime/arch/x86_64/quick_method_frame_info_x86_64.h
index 53aa212..72d7e99 100644
--- a/runtime/arch/x86_64/quick_method_frame_info_x86_64.h
+++ b/runtime/arch/x86_64/quick_method_frame_info_x86_64.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_ARCH_X86_64_QUICK_METHOD_FRAME_INFO_X86_64_H_
 #define ART_RUNTIME_ARCH_X86_64_QUICK_METHOD_FRAME_INFO_X86_64_H_
 
+#include "base/bit_utils.h"
 #include "quick/quick_method_frame_info.h"
 #include "registers_x86_64.h"
 #include "runtime.h"  // for Runtime::CalleeSaveType.
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 0f306e8..5cfce41 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -14,92 +14,102 @@
  * 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"
 #include "runtime-inl.h"
+#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;
 }
 
@@ -107,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;
 }
 
@@ -128,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;
 }
 
@@ -164,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:
@@ -172,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:
@@ -236,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);
 }
 
@@ -260,7 +267,7 @@
 }
 
 inline bool ArtMethod::IsRuntimeMethod() {
-  return GetDexMethodIndex() == DexFile::kDexNoIndex;
+  return dex_method_index_ == DexFile::kDexNoIndex;
 }
 
 inline bool ArtMethod::IsCalleeSaveMethod() {
@@ -316,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>";
@@ -369,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) {
@@ -471,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.VisitRootIfNonNull(declaring_class_.AddressWithoutBarrier());
+  visitor.VisitRootIfNonNull(dex_cache_resolved_methods_.AddressWithoutBarrier());
+  visitor.VisitRootIfNonNull(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 83%
rename from runtime/mirror/art_method.cc
rename to runtime/art_method.cc
index 9518c9d..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;
 }
 
@@ -201,29 +182,32 @@
   uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(entry_point);
   if (IsOptimized(sizeof(void*))) {
     CodeInfo code_info = GetOptimizedCodeInfo();
-    return code_info.GetStackMapForNativePcOffset(sought_offset).GetDexPc(code_info);
-  }
-
-  MappingTable table(entry_point != nullptr ?
-      GetMappingTable(EntryPointToCodePointer(entry_point), sizeof(void*)) : nullptr);
-  if (table.TotalSize() == 0) {
-    // NOTE: Special methods (see Mir2Lir::GenSpecialCase()) have an empty mapping
-    // but they have no suspend checks and, consequently, we never call ToDexPc() for them.
-    DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this);
-    return DexFile::kDexNoIndex;   // Special no mapping case
-  }
-  // Assume the caller wants a pc-to-dex mapping so check here first.
-  typedef MappingTable::PcToDexIterator It;
-  for (It cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
-    if (cur.NativePcOffset() == sought_offset) {
-      return cur.DexPc();
+    StackMap stack_map = code_info.GetStackMapForNativePcOffset(sought_offset);
+    if (stack_map.IsValid()) {
+      return stack_map.GetDexPc(code_info);
     }
-  }
-  // Now check dex-to-pc mappings.
-  typedef MappingTable::DexToPcIterator It2;
-  for (It2 cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
-    if (cur.NativePcOffset() == sought_offset) {
-      return cur.DexPc();
+  } else {
+    MappingTable table(entry_point != nullptr ?
+        GetMappingTable(EntryPointToCodePointer(entry_point), sizeof(void*)) : nullptr);
+    if (table.TotalSize() == 0) {
+      // NOTE: Special methods (see Mir2Lir::GenSpecialCase()) have an empty mapping
+      // but they have no suspend checks and, consequently, we never call ToDexPc() for them.
+      DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this);
+      return DexFile::kDexNoIndex;   // Special no mapping case
+    }
+    // Assume the caller wants a pc-to-dex mapping so check here first.
+    typedef MappingTable::PcToDexIterator It;
+    for (It cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
+      if (cur.NativePcOffset() == sought_offset) {
+        return cur.DexPc();
+      }
+    }
+    // Now check dex-to-pc mappings.
+    typedef MappingTable::DexToPcIterator It2;
+    for (It2 cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
+      if (cur.NativePcOffset() == sought_offset) {
+        return cur.DexPc();
+      }
     }
   }
   if (abort_on_failure) {
@@ -264,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);
@@ -283,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.
@@ -293,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;
@@ -375,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
@@ -390,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.
@@ -405,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.
@@ -481,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
@@ -497,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
@@ -516,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());
   }
 
@@ -570,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/barrier.cc b/runtime/barrier.cc
index f80a65f..d21f551 100644
--- a/runtime/barrier.cc
+++ b/runtime/barrier.cc
@@ -17,6 +17,7 @@
 #include "barrier.h"
 
 #include "base/mutex.h"
+#include "base/time_utils.h"
 #include "thread.h"
 
 namespace art {
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 ab5968c..d9723b5 100644
--- a/runtime/base/arena_allocator.h
+++ b/runtime/base/arena_allocator.h
@@ -20,10 +20,10 @@
 #include <stdint.h>
 #include <stddef.h>
 
+#include "base/bit_utils.h"
 #include "debug_stack.h"
 #include "macros.h"
 #include "mutex.h"
-#include "utils.h"
 
 namespace art {
 
@@ -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/bit_utils.h b/runtime/base/bit_utils.h
new file mode 100644
index 0000000..7972158
--- /dev/null
+++ b/runtime/base/bit_utils.h
@@ -0,0 +1,337 @@
+/*
+ * 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_BASE_BIT_UTILS_H_
+#define ART_RUNTIME_BASE_BIT_UTILS_H_
+
+#include <iterator>
+#include <limits>
+#include <type_traits>
+
+#include "base/logging.h"
+#include "base/iteration_range.h"
+
+namespace art {
+
+template<typename T>
+static constexpr int CLZ(T x) {
+  static_assert(std::is_integral<T>::value, "T must be integral");
+  // TODO: assert unsigned. There is currently many uses with signed values.
+  static_assert(sizeof(T) <= sizeof(long long),  // NOLINT [runtime/int] [4]
+                "T too large, must be smaller than long long");
+  return (sizeof(T) == sizeof(uint32_t))
+      ? __builtin_clz(x)  // TODO: __builtin_clz[ll] has undefined behavior for x=0
+      : __builtin_clzll(x);
+}
+
+template<typename T>
+static constexpr int CTZ(T x) {
+  static_assert(std::is_integral<T>::value, "T must be integral");
+  // TODO: assert unsigned. There is currently many uses with signed values.
+  return (sizeof(T) == sizeof(uint32_t))
+      ? __builtin_ctz(x)
+      : __builtin_ctzll(x);
+}
+
+template<typename T>
+static constexpr int POPCOUNT(T x) {
+  return (sizeof(T) == sizeof(uint32_t))
+      ? __builtin_popcount(x)
+      : __builtin_popcountll(x);
+}
+
+// Find the bit position of the most significant bit (0-based), or -1 if there were no bits set.
+template <typename T>
+static constexpr ssize_t MostSignificantBit(T value) {
+  static_assert(std::is_integral<T>::value, "T must be integral");
+  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(std::numeric_limits<T>::radix == 2, "Unexpected radix!");
+  return (value == 0) ? -1 : std::numeric_limits<T>::digits - 1 - CLZ(value);
+}
+
+// Find the bit position of the least significant bit (0-based), or -1 if there were no bits set.
+template <typename T>
+static constexpr ssize_t LeastSignificantBit(T value) {
+  static_assert(std::is_integral<T>::value, "T must be integral");
+  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  return (value == 0) ? -1 : CTZ(value);
+}
+
+// How many bits (minimally) does it take to store the constant 'value'? i.e. 1 for 1, 3 for 5, etc.
+template <typename T>
+static constexpr size_t MinimumBitsToStore(T value) {
+  return static_cast<size_t>(MostSignificantBit(value) + 1);
+}
+
+template <typename T>
+static constexpr inline T RoundUpToPowerOfTwo(T x) {
+  static_assert(std::is_integral<T>::value, "T must be integral");
+  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  // NOTE: Undefined if x > (1 << (std::numeric_limits<T>::digits - 1)).
+  return (x < 2u) ? x : static_cast<T>(1u) << (std::numeric_limits<T>::digits - CLZ(x - 1u));
+}
+
+template<typename T>
+static constexpr bool IsPowerOfTwo(T x) {
+  static_assert(std::is_integral<T>::value, "T must be integral");
+  // TODO: assert unsigned. There is currently many uses with signed values.
+  return (x & (x - 1)) == 0;
+}
+
+template<typename T>
+static inline int WhichPowerOf2(T x) {
+  static_assert(std::is_integral<T>::value, "T must be integral");
+  // TODO: assert unsigned. There is currently many uses with signed values.
+  DCHECK((x != 0) && IsPowerOfTwo(x));
+  return CTZ(x);
+}
+
+// For rounding integers.
+// NOTE: In the absence of std::omit_from_type_deduction<T> or std::identity<T>, use std::decay<T>.
+template<typename T>
+static constexpr T RoundDown(T x, typename std::decay<T>::type n) WARN_UNUSED;
+
+template<typename T>
+static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
+  return
+      DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))
+      (x & -n);
+}
+
+template<typename T>
+static constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) WARN_UNUSED;
+
+template<typename T>
+static constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) {
+  return RoundDown(x + n - 1, n);
+}
+
+// For aligning pointers.
+template<typename T>
+static inline T* AlignDown(T* x, uintptr_t n) WARN_UNUSED;
+
+template<typename T>
+static inline T* AlignDown(T* x, uintptr_t n) {
+  return reinterpret_cast<T*>(RoundDown(reinterpret_cast<uintptr_t>(x), n));
+}
+
+template<typename T>
+static inline T* AlignUp(T* x, uintptr_t n) WARN_UNUSED;
+
+template<typename T>
+static inline T* AlignUp(T* x, uintptr_t n) {
+  return reinterpret_cast<T*>(RoundUp(reinterpret_cast<uintptr_t>(x), n));
+}
+
+template<int n, typename T>
+static inline bool IsAligned(T x) {
+  static_assert((n & (n - 1)) == 0, "n is not a power of two");
+  return (x & (n - 1)) == 0;
+}
+
+template<int n, typename T>
+static inline bool IsAligned(T* x) {
+  return IsAligned<n>(reinterpret_cast<const uintptr_t>(x));
+}
+
+template<typename T>
+static inline bool IsAlignedParam(T x, int n) {
+  return (x & (n - 1)) == 0;
+}
+
+#define CHECK_ALIGNED(value, alignment) \
+  CHECK(::art::IsAligned<alignment>(value)) << reinterpret_cast<const void*>(value)
+
+#define DCHECK_ALIGNED(value, alignment) \
+  DCHECK(::art::IsAligned<alignment>(value)) << reinterpret_cast<const void*>(value)
+
+#define DCHECK_ALIGNED_PARAM(value, alignment) \
+  DCHECK(::art::IsAlignedParam(value, alignment)) << reinterpret_cast<const void*>(value)
+
+// Like sizeof, but count how many bits a type takes. Pass type explicitly.
+template <typename T>
+static constexpr size_t BitSizeOf() {
+  static_assert(std::is_integral<T>::value, "T must be integral");
+  typedef typename std::make_unsigned<T>::type unsigned_type;
+  static_assert(sizeof(T) == sizeof(unsigned_type), "Unexpected type size mismatch!");
+  static_assert(std::numeric_limits<unsigned_type>::radix == 2, "Unexpected radix!");
+  return std::numeric_limits<unsigned_type>::digits;
+}
+
+// Like sizeof, but count how many bits a type takes. Infers type from parameter.
+template <typename T>
+static constexpr size_t BitSizeOf(T /*x*/) {
+  return BitSizeOf<T>();
+}
+
+static inline uint16_t Low16Bits(uint32_t value) {
+  return static_cast<uint16_t>(value);
+}
+
+static inline uint16_t High16Bits(uint32_t value) {
+  return static_cast<uint16_t>(value >> 16);
+}
+
+static inline uint32_t Low32Bits(uint64_t value) {
+  return static_cast<uint32_t>(value);
+}
+
+static inline uint32_t High32Bits(uint64_t value) {
+  return static_cast<uint32_t>(value >> 32);
+}
+
+// Check whether an N-bit two's-complement representation can hold value.
+template <typename T>
+static inline bool IsInt(size_t N, T value) {
+  if (N == BitSizeOf<T>()) {
+    return true;
+  } else {
+    CHECK_LT(0u, N);
+    CHECK_LT(N, BitSizeOf<T>());
+    T limit = static_cast<T>(1) << (N - 1u);
+    return (-limit <= value) && (value < limit);
+  }
+}
+
+template <typename T>
+static constexpr T GetIntLimit(size_t bits) {
+  return
+      DCHECK_CONSTEXPR(bits > 0, "bits cannot be zero", 0)
+      DCHECK_CONSTEXPR(bits < BitSizeOf<T>(), "kBits must be < max.", 0)
+      static_cast<T>(1) << (bits - 1);
+}
+
+template <size_t kBits, typename T>
+static constexpr bool IsInt(T value) {
+  static_assert(kBits > 0, "kBits cannot be zero.");
+  static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
+  static_assert(std::is_signed<T>::value, "Needs a signed type.");
+  // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
+  // trivially true.
+  return (kBits == BitSizeOf<T>()) ?
+      true :
+      (-GetIntLimit<T>(kBits) <= value) && (value < GetIntLimit<T>(kBits));
+}
+
+template <size_t kBits, typename T>
+static constexpr bool IsUint(T value) {
+  static_assert(kBits > 0, "kBits cannot be zero.");
+  static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
+  static_assert(std::is_integral<T>::value, "Needs an integral type.");
+  // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
+  // trivially true.
+  // NOTE: To avoid triggering assertion in GetIntLimit(kBits+1) if kBits+1==BitSizeOf<T>(),
+  // use GetIntLimit(kBits)*2u. The unsigned arithmetic works well for us if it overflows.
+  return (0 <= value) &&
+      (kBits == BitSizeOf<T>() ||
+          (static_cast<typename std::make_unsigned<T>::type>(value) <=
+               GetIntLimit<typename std::make_unsigned<T>::type>(kBits) * 2u - 1u));
+}
+
+template <size_t kBits, typename T>
+static constexpr bool IsAbsoluteUint(T value) {
+  static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
+  static_assert(std::is_integral<T>::value, "Needs an integral type.");
+  typedef typename std::make_unsigned<T>::type unsigned_type;
+  return (kBits == BitSizeOf<T>())
+      ? true
+      : IsUint<kBits>(value < 0
+                      ? static_cast<unsigned_type>(-1 - value) + 1u  // Avoid overflow.
+                      : static_cast<unsigned_type>(value));
+}
+
+// Using the Curiously Recurring Template Pattern to implement everything shared
+// by LowToHighBitIterator and HighToLowBitIterator, i.e. everything but operator*().
+template <typename T, typename Iter>
+class BitIteratorBase
+    : public std::iterator<std::forward_iterator_tag, uint32_t, ptrdiff_t, void, void> {
+  static_assert(std::is_integral<T>::value, "T must be integral");
+  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+
+  static_assert(sizeof(T) == sizeof(uint32_t) || sizeof(T) == sizeof(uint64_t), "Unsupported size");
+
+ public:
+  BitIteratorBase() : bits_(0u) { }
+  explicit BitIteratorBase(T bits) : bits_(bits) { }
+
+  Iter& operator++() {
+    DCHECK_NE(bits_, 0u);
+    uint32_t bit = *static_cast<Iter&>(*this);
+    bits_ &= ~(static_cast<T>(1u) << bit);
+    return static_cast<Iter&>(*this);
+  }
+
+  Iter& operator++(int) {
+    Iter tmp(static_cast<Iter&>(*this));
+    ++*this;
+    return tmp;
+  }
+
+ protected:
+  T bits_;
+
+  template <typename U, typename I>
+  friend bool operator==(const BitIteratorBase<U, I>& lhs, const BitIteratorBase<U, I>& rhs);
+};
+
+template <typename T, typename Iter>
+bool operator==(const BitIteratorBase<T, Iter>& lhs, const BitIteratorBase<T, Iter>& rhs) {
+  return lhs.bits_ == rhs.bits_;
+}
+
+template <typename T, typename Iter>
+bool operator!=(const BitIteratorBase<T, Iter>& lhs, const BitIteratorBase<T, Iter>& rhs) {
+  return !(lhs == rhs);
+}
+
+template <typename T>
+class LowToHighBitIterator : public BitIteratorBase<T, LowToHighBitIterator<T>> {
+ public:
+  using BitIteratorBase<T, LowToHighBitIterator<T>>::BitIteratorBase;
+
+  uint32_t operator*() const {
+    DCHECK_NE(this->bits_, 0u);
+    return CTZ(this->bits_);
+  }
+};
+
+template <typename T>
+class HighToLowBitIterator : public BitIteratorBase<T, HighToLowBitIterator<T>> {
+ public:
+  using BitIteratorBase<T, HighToLowBitIterator<T>>::BitIteratorBase;
+
+  uint32_t operator*() const {
+    DCHECK_NE(this->bits_, 0u);
+    static_assert(std::numeric_limits<T>::radix == 2, "Unexpected radix!");
+    return std::numeric_limits<T>::digits - 1u - CLZ(this->bits_);
+  }
+};
+
+template <typename T>
+IterationRange<LowToHighBitIterator<T>> LowToHighBits(T bits) {
+  return IterationRange<LowToHighBitIterator<T>>(
+      LowToHighBitIterator<T>(bits), LowToHighBitIterator<T>());
+}
+
+template <typename T>
+IterationRange<HighToLowBitIterator<T>> HighToLowBits(T bits) {
+  return IterationRange<HighToLowBitIterator<T>>(
+      HighToLowBitIterator<T>(bits), HighToLowBitIterator<T>());
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_BASE_BIT_UTILS_H_
diff --git a/runtime/base/bit_utils_test.cc b/runtime/base/bit_utils_test.cc
new file mode 100644
index 0000000..77bd0b8
--- /dev/null
+++ b/runtime/base/bit_utils_test.cc
@@ -0,0 +1,400 @@
+/*
+ * 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.
+ */
+
+#include <vector>
+
+#include "bit_utils.h"
+
+#include "gtest/gtest.h"
+
+namespace art {
+
+// NOTE: CLZ(0u) is undefined.
+static_assert(31 == CLZ<uint32_t>(1u), "TestCLZ32#1");
+static_assert(30 == CLZ<uint32_t>(2u), "TestCLZ32#2");
+static_assert(16 == CLZ<uint32_t>(0x00008765u), "TestCLZ32#3");
+static_assert(15 == CLZ<uint32_t>(0x00012345u), "TestCLZ32#4");
+static_assert(1 == CLZ<uint32_t>(0x43214321u), "TestCLZ32#5");
+static_assert(0 == CLZ<uint32_t>(0x87654321u), "TestCLZ32#6");
+
+// NOTE: CLZ(0ull) is undefined.
+static_assert(63 == CLZ<uint64_t>(UINT64_C(1)), "TestCLZ64#1");
+static_assert(62 == CLZ<uint64_t>(UINT64_C(3)), "TestCLZ64#2");
+static_assert(48 == CLZ<uint64_t>(UINT64_C(0x00008765)), "TestCLZ64#3");
+static_assert(32 == CLZ<uint64_t>(UINT64_C(0x87654321)), "TestCLZ64#4");
+static_assert(31 == CLZ<uint64_t>(UINT64_C(0x123456789)), "TestCLZ64#5");
+static_assert(16 == CLZ<uint64_t>(UINT64_C(0x876543211234)), "TestCLZ64#6");
+static_assert(1 == CLZ<uint64_t>(UINT64_C(0x4321432187654321)), "TestCLZ64#7");
+static_assert(0 == CLZ<uint64_t>(UINT64_C(0x8765432187654321)), "TestCLZ64#8");
+
+// NOTE: CTZ(0u) is undefined.
+static_assert(0 == CTZ<uint32_t>(1u), "TestCTZ32#1");
+static_assert(1 == CTZ<uint32_t>(2u), "TestCTZ32#2");
+static_assert(15 == CTZ<uint32_t>(0x45678000u), "TestCTZ32#3");
+static_assert(16 == CTZ<uint32_t>(0x43210000u), "TestCTZ32#4");
+static_assert(30 == CTZ<uint32_t>(0xc0000000u), "TestCTZ32#5");
+static_assert(31 == CTZ<uint32_t>(0x80000000u), "TestCTZ32#6");
+
+// NOTE: CTZ(0ull) is undefined.
+static_assert(0 == CTZ<uint64_t>(UINT64_C(1)), "TestCTZ64#1");
+static_assert(1 == CTZ<uint64_t>(UINT64_C(2)), "TestCTZ64#2");
+static_assert(16 == CTZ<uint64_t>(UINT64_C(0x43210000)), "TestCTZ64#3");
+static_assert(31 == CTZ<uint64_t>(UINT64_C(0x80000000)), "TestCTZ64#4");
+static_assert(32 == CTZ<uint64_t>(UINT64_C(0x8765432100000000)), "TestCTZ64#5");
+static_assert(48 == CTZ<uint64_t>(UINT64_C(0x4321000000000000)), "TestCTZ64#6");
+static_assert(62 == CTZ<uint64_t>(UINT64_C(0x4000000000000000)), "TestCTZ64#7");
+static_assert(63 == CTZ<uint64_t>(UINT64_C(0x8000000000000000)), "TestCTZ64#8");
+
+static_assert(0 == POPCOUNT<uint32_t>(0u), "TestPOPCOUNT32#1");
+static_assert(1 == POPCOUNT<uint32_t>(8u), "TestPOPCOUNT32#2");
+static_assert(15 == POPCOUNT<uint32_t>(0x55555554u), "TestPOPCOUNT32#3");
+static_assert(16 == POPCOUNT<uint32_t>(0xaaaaaaaau), "TestPOPCOUNT32#4");
+static_assert(31 == POPCOUNT<uint32_t>(0xfffffffeu), "TestPOPCOUNT32#5");
+static_assert(32 == POPCOUNT<uint32_t>(0xffffffffu), "TestPOPCOUNT32#6");
+
+static_assert(0 == POPCOUNT<uint64_t>(UINT64_C(0)), "TestPOPCOUNT64#1");
+static_assert(1 == POPCOUNT<uint64_t>(UINT64_C(0x40000)), "TestPOPCOUNT64#2");
+static_assert(16 == POPCOUNT<uint64_t>(UINT64_C(0x1414141482828282)), "TestPOPCOUNT64#3");
+static_assert(31 == POPCOUNT<uint64_t>(UINT64_C(0x0000ffff00007fff)), "TestPOPCOUNT64#4");
+static_assert(32 == POPCOUNT<uint64_t>(UINT64_C(0x5555555555555555)), "TestPOPCOUNT64#5");
+static_assert(48 == POPCOUNT<uint64_t>(UINT64_C(0x7777bbbbddddeeee)), "TestPOPCOUNT64#6");
+static_assert(63 == POPCOUNT<uint64_t>(UINT64_C(0x7fffffffffffffff)), "TestPOPCOUNT64#7");
+static_assert(64 == POPCOUNT<uint64_t>(UINT64_C(0xffffffffffffffff)), "TestPOPCOUNT64#8");
+
+static_assert(-1 == MostSignificantBit<uint32_t>(0u), "TestMSB32#1");
+static_assert(0 == MostSignificantBit<uint32_t>(1u), "TestMSB32#2");
+static_assert(31 == MostSignificantBit<uint32_t>(~static_cast<uint32_t>(0u)), "TestMSB32#3");
+static_assert(2 == MostSignificantBit<uint32_t>(0b110), "TestMSB32#4");
+static_assert(2 == MostSignificantBit<uint32_t>(0b100), "TestMSB32#5");
+
+static_assert(-1 == MostSignificantBit<uint64_t>(UINT64_C(0)), "TestMSB64#1");
+static_assert(0 == MostSignificantBit<uint64_t>(UINT64_C(1)), "TestMSB64#2");
+static_assert(63 == MostSignificantBit<uint64_t>(~UINT64_C(0)), "TestMSB64#3");
+static_assert(34 == MostSignificantBit<uint64_t>(UINT64_C(0x700000000)), "TestMSB64#4");
+static_assert(34 == MostSignificantBit<uint64_t>(UINT64_C(0x777777777)), "TestMSB64#5");
+
+static_assert(-1 == LeastSignificantBit<uint32_t>(0u), "TestLSB32#1");
+static_assert(0 == LeastSignificantBit<uint32_t>(1u), "TestLSB32#1");
+static_assert(0 == LeastSignificantBit<uint32_t>(~static_cast<uint32_t>(0u)), "TestLSB32#1");
+static_assert(1 == LeastSignificantBit<uint32_t>(0b110), "TestLSB32#1");
+static_assert(2 == LeastSignificantBit<uint32_t>(0b100), "TestLSB32#1");
+
+static_assert(-1 == LeastSignificantBit<uint64_t>(UINT64_C(0)), "TestLSB64#1");
+static_assert(0 == LeastSignificantBit<uint64_t>(UINT64_C(1)), "TestLSB64#2");
+static_assert(0 == LeastSignificantBit<uint64_t>(~UINT64_C(0)), "TestLSB64#3");
+static_assert(12 == LeastSignificantBit<uint64_t>(UINT64_C(0x5000)), "TestLSB64#4");
+static_assert(48 == LeastSignificantBit<uint64_t>(UINT64_C(0x5555000000000000)), "TestLSB64#5");
+
+static_assert(0u == MinimumBitsToStore<uint32_t>(0u), "TestMinBits2Store32#1");
+static_assert(1u == MinimumBitsToStore<uint32_t>(1u), "TestMinBits2Store32#2");
+static_assert(2u == MinimumBitsToStore<uint32_t>(0b10u), "TestMinBits2Store32#3");
+static_assert(2u == MinimumBitsToStore<uint32_t>(0b11u), "TestMinBits2Store32#4");
+static_assert(3u == MinimumBitsToStore<uint32_t>(0b100u), "TestMinBits2Store32#5");
+static_assert(3u == MinimumBitsToStore<uint32_t>(0b110u), "TestMinBits2Store32#6");
+static_assert(3u == MinimumBitsToStore<uint32_t>(0b101u), "TestMinBits2Store32#7");
+static_assert(8u == MinimumBitsToStore<uint32_t>(0xFFu), "TestMinBits2Store32#8");
+static_assert(32u == MinimumBitsToStore<uint32_t>(~static_cast<uint32_t>(0u)),
+              "TestMinBits2Store32#9");
+
+static_assert(0u == MinimumBitsToStore<uint64_t>(UINT64_C(0)), "TestMinBits2Store64#1");
+static_assert(1u == MinimumBitsToStore<uint64_t>(UINT64_C(1)), "TestMinBits2Store64#2");
+static_assert(2u == MinimumBitsToStore<uint64_t>(UINT64_C(0b10)), "TestMinBits2Store64#3");
+static_assert(2u == MinimumBitsToStore<uint64_t>(UINT64_C(0b11)), "TestMinBits2Store64#4");
+static_assert(3u == MinimumBitsToStore<uint64_t>(UINT64_C(0b100)), "TestMinBits2Store64#5");
+static_assert(3u == MinimumBitsToStore<uint64_t>(UINT64_C(0b110)), "TestMinBits2Store64#6");
+static_assert(3u == MinimumBitsToStore<uint64_t>(UINT64_C(0b101)), "TestMinBits2Store64#7");
+static_assert(8u == MinimumBitsToStore<uint64_t>(UINT64_C(0xFF)), "TestMinBits2Store64#8");
+static_assert(32u == MinimumBitsToStore<uint64_t>(UINT64_C(0xFFFFFFFF)), "TestMinBits2Store64#9");
+static_assert(33u == MinimumBitsToStore<uint64_t>(UINT64_C(0x1FFFFFFFF)), "TestMinBits2Store64#10");
+static_assert(64u == MinimumBitsToStore<uint64_t>(~UINT64_C(0)), "TestMinBits2Store64#11");
+
+static_assert(0 == RoundUpToPowerOfTwo<uint32_t>(0u), "TestRoundUpPowerOfTwo32#1");
+static_assert(1 == RoundUpToPowerOfTwo<uint32_t>(1u), "TestRoundUpPowerOfTwo32#2");
+static_assert(2 == RoundUpToPowerOfTwo<uint32_t>(2u), "TestRoundUpPowerOfTwo32#3");
+static_assert(4 == RoundUpToPowerOfTwo<uint32_t>(3u), "TestRoundUpPowerOfTwo32#4");
+static_assert(8 == RoundUpToPowerOfTwo<uint32_t>(7u), "TestRoundUpPowerOfTwo32#5");
+static_assert(0x40000u == RoundUpToPowerOfTwo<uint32_t>(0x2aaaau),
+              "TestRoundUpPowerOfTwo32#6");
+static_assert(0x80000000u == RoundUpToPowerOfTwo<uint32_t>(0x40000001u),
+              "TestRoundUpPowerOfTwo32#7");
+static_assert(0x80000000u == RoundUpToPowerOfTwo<uint32_t>(0x80000000u),
+              "TestRoundUpPowerOfTwo32#8");
+
+static_assert(0 == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(0)), "TestRoundUpPowerOfTwo64#1");
+static_assert(1 == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(1)), "TestRoundUpPowerOfTwo64#2");
+static_assert(2 == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(2)), "TestRoundUpPowerOfTwo64#3");
+static_assert(4 == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(3)), "TestRoundUpPowerOfTwo64#4");
+static_assert(8 == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(7)), "TestRoundUpPowerOfTwo64#5");
+static_assert(UINT64_C(0x40000) == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(0x2aaaa)),
+              "TestRoundUpPowerOfTwo64#6");
+static_assert(
+    UINT64_C(0x8000000000000000) == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(0x4000000000000001)),
+    "TestRoundUpPowerOfTwo64#7");
+static_assert(
+    UINT64_C(0x8000000000000000) == RoundUpToPowerOfTwo<uint64_t>(UINT64_C(0x8000000000000000)),
+    "TestRoundUpPowerOfTwo64#8");
+
+static constexpr int64_t kInt32MinMinus1 =
+    static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1;
+static constexpr int64_t kInt32MaxPlus1 =
+    static_cast<int64_t>(std::numeric_limits<int32_t>::max()) + 1;
+static constexpr int64_t kUint32MaxPlus1 =
+    static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) + 1;
+
+TEST(BitUtilsTest, TestIsInt32) {
+  EXPECT_FALSE(IsInt<int32_t>(1, -2));
+  EXPECT_TRUE(IsInt<int32_t>(1, -1));
+  EXPECT_TRUE(IsInt<int32_t>(1, 0));
+  EXPECT_FALSE(IsInt<int32_t>(1, 1));
+  EXPECT_FALSE(IsInt<int32_t>(4, -9));
+  EXPECT_TRUE(IsInt<int32_t>(4, -8));
+  EXPECT_TRUE(IsInt<int32_t>(4, 7));
+  EXPECT_FALSE(IsInt<int32_t>(4, 8));
+  EXPECT_FALSE(IsInt<int32_t>(31, std::numeric_limits<int32_t>::min()));
+  EXPECT_FALSE(IsInt<int32_t>(31, std::numeric_limits<int32_t>::max()));
+  EXPECT_TRUE(IsInt<int32_t>(32, std::numeric_limits<int32_t>::min()));
+  EXPECT_TRUE(IsInt<int32_t>(32, std::numeric_limits<int32_t>::max()));
+}
+
+TEST(BitUtilsTest, TestIsInt64) {
+  EXPECT_FALSE(IsInt<int64_t>(1, -2));
+  EXPECT_TRUE(IsInt<int64_t>(1, -1));
+  EXPECT_TRUE(IsInt<int64_t>(1, 0));
+  EXPECT_FALSE(IsInt<int64_t>(1, 1));
+  EXPECT_FALSE(IsInt<int64_t>(4, -9));
+  EXPECT_TRUE(IsInt<int64_t>(4, -8));
+  EXPECT_TRUE(IsInt<int64_t>(4, 7));
+  EXPECT_FALSE(IsInt<int64_t>(4, 8));
+  EXPECT_FALSE(IsInt<int64_t>(31, std::numeric_limits<int32_t>::min()));
+  EXPECT_FALSE(IsInt<int64_t>(31, std::numeric_limits<int32_t>::max()));
+  EXPECT_TRUE(IsInt<int64_t>(32, std::numeric_limits<int32_t>::min()));
+  EXPECT_TRUE(IsInt<int64_t>(32, std::numeric_limits<int32_t>::max()));
+  EXPECT_FALSE(IsInt<int64_t>(32, kInt32MinMinus1));
+  EXPECT_FALSE(IsInt<int64_t>(32, kInt32MaxPlus1));
+  EXPECT_FALSE(IsInt<int64_t>(63, std::numeric_limits<int64_t>::min()));
+  EXPECT_FALSE(IsInt<int64_t>(63, std::numeric_limits<int64_t>::max()));
+  EXPECT_TRUE(IsInt<int64_t>(64, std::numeric_limits<int64_t>::min()));
+  EXPECT_TRUE(IsInt<int64_t>(64, std::numeric_limits<int64_t>::max()));
+}
+
+static_assert(!IsInt<1, int32_t>(-2), "TestIsInt32#1");
+static_assert(IsInt<1, int32_t>(-1), "TestIsInt32#2");
+static_assert(IsInt<1, int32_t>(0), "TestIsInt32#3");
+static_assert(!IsInt<1, int32_t>(1), "TestIsInt32#4");
+static_assert(!IsInt<4, int32_t>(-9), "TestIsInt32#5");
+static_assert(IsInt<4, int32_t>(-8), "TestIsInt32#6");
+static_assert(IsInt<4, int32_t>(7), "TestIsInt32#7");
+static_assert(!IsInt<4, int32_t>(8), "TestIsInt32#8");
+static_assert(!IsInt<31, int32_t>(std::numeric_limits<int32_t>::min()), "TestIsInt32#9");
+static_assert(!IsInt<31, int32_t>(std::numeric_limits<int32_t>::max()), "TestIsInt32#10");
+static_assert(IsInt<32, int32_t>(std::numeric_limits<int32_t>::min()), "TestIsInt32#11");
+static_assert(IsInt<32, int32_t>(std::numeric_limits<int32_t>::max()), "TestIsInt32#12");
+
+static_assert(!IsInt<1, int64_t>(-2), "TestIsInt64#1");
+static_assert(IsInt<1, int64_t>(-1), "TestIsInt64#2");
+static_assert(IsInt<1, int64_t>(0), "TestIsInt64#3");
+static_assert(!IsInt<1, int64_t>(1), "TestIsInt64#4");
+static_assert(!IsInt<4, int64_t>(-9), "TestIsInt64#5");
+static_assert(IsInt<4, int64_t>(-8), "TestIsInt64#6");
+static_assert(IsInt<4, int64_t>(7), "TestIsInt64#7");
+static_assert(!IsInt<4, int64_t>(8), "TestIsInt64#8");
+static_assert(!IsInt<31, int64_t>(std::numeric_limits<int32_t>::min()), "TestIsInt64#9");
+static_assert(!IsInt<31, int64_t>(std::numeric_limits<int32_t>::max()), "TestIsInt64#10");
+static_assert(IsInt<32, int64_t>(std::numeric_limits<int32_t>::min()), "TestIsInt64#11");
+static_assert(IsInt<32, int64_t>(std::numeric_limits<int32_t>::max()), "TestIsInt64#12");
+static_assert(!IsInt<32, int64_t>(kInt32MinMinus1), "TestIsInt64#13");
+static_assert(!IsInt<32, int64_t>(kInt32MaxPlus1), "TestIsInt64#14");
+static_assert(!IsInt<63, int64_t>(std::numeric_limits<int64_t>::min()), "TestIsInt64#15");
+static_assert(!IsInt<63, int64_t>(std::numeric_limits<int64_t>::max()), "TestIsInt64#16");
+static_assert(IsInt<64, int64_t>(std::numeric_limits<int64_t>::min()), "TestIsInt64#17");
+static_assert(IsInt<64, int64_t>(std::numeric_limits<int64_t>::max()), "TestIsInt64#18");
+
+static_assert(!IsUint<1, int32_t>(-1), "TestIsUint32#1");
+static_assert(IsUint<1, int32_t>(0), "TestIsUint32#2");
+static_assert(IsUint<1, int32_t>(1), "TestIsUint32#3");
+static_assert(!IsUint<1, int32_t>(2), "TestIsUint32#4");
+static_assert(!IsUint<4, int32_t>(-1), "TestIsUint32#5");
+static_assert(IsUint<4, int32_t>(0), "TestIsUint32#6");
+static_assert(IsUint<4, int32_t>(15), "TestIsUint32#7");
+static_assert(!IsUint<4, int32_t>(16), "TestIsUint32#8");
+static_assert(!IsUint<30, int32_t>(std::numeric_limits<int32_t>::max()), "TestIsUint32#9");
+static_assert(IsUint<31, int32_t>(std::numeric_limits<int32_t>::max()), "TestIsUint32#10");
+static_assert(!IsUint<32, int32_t>(-1), "TestIsUint32#11");
+static_assert(IsUint<32, int32_t>(0), "TestIsUint32#11");
+static_assert(IsUint<32, uint32_t>(static_cast<uint32_t>(-1)), "TestIsUint32#12");
+
+static_assert(!IsUint<1, int64_t>(-1), "TestIsUint64#1");
+static_assert(IsUint<1, int64_t>(0), "TestIsUint64#2");
+static_assert(IsUint<1, int64_t>(1), "TestIsUint64#3");
+static_assert(!IsUint<1, int64_t>(2), "TestIsUint64#4");
+static_assert(!IsUint<4, int64_t>(-1), "TestIsUint64#5");
+static_assert(IsUint<4, int64_t>(0), "TestIsUint64#6");
+static_assert(IsUint<4, int64_t>(15), "TestIsUint64#7");
+static_assert(!IsUint<4, int64_t>(16), "TestIsUint64#8");
+static_assert(!IsUint<30, int64_t>(std::numeric_limits<int32_t>::max()), "TestIsUint64#9");
+static_assert(IsUint<31, int64_t>(std::numeric_limits<int32_t>::max()), "TestIsUint64#10");
+static_assert(!IsUint<62, int64_t>(std::numeric_limits<int64_t>::max()), "TestIsUint64#11");
+static_assert(IsUint<63, int64_t>(std::numeric_limits<int64_t>::max()), "TestIsUint64#12");
+static_assert(!IsUint<64, int64_t>(-1), "TestIsUint64#13");
+static_assert(IsUint<64, int64_t>(0), "TestIsUint64#14");
+static_assert(IsUint<64, uint64_t>(static_cast<uint32_t>(-1)), "TestIsUint64#15");
+
+static_assert(!IsAbsoluteUint<1, int32_t>(-2), "TestIsAbsoluteUint32#1");
+static_assert(IsAbsoluteUint<1, int32_t>(-1), "TestIsAbsoluteUint32#2");
+static_assert(IsAbsoluteUint<1, int32_t>(0), "TestIsAbsoluteUint32#3");
+static_assert(IsAbsoluteUint<1, int32_t>(1), "TestIsAbsoluteUint32#4");
+static_assert(!IsAbsoluteUint<1, int32_t>(2), "TestIsAbsoluteUint32#5");
+static_assert(!IsAbsoluteUint<4, int32_t>(-16), "TestIsAbsoluteUint32#6");
+static_assert(IsAbsoluteUint<4, int32_t>(-15), "TestIsAbsoluteUint32#7");
+static_assert(IsAbsoluteUint<4, int32_t>(0), "TestIsAbsoluteUint32#8");
+static_assert(IsAbsoluteUint<4, int32_t>(15), "TestIsAbsoluteUint32#9");
+static_assert(!IsAbsoluteUint<4, int32_t>(16), "TestIsAbsoluteUint32#10");
+static_assert(!IsAbsoluteUint<30, int32_t>(std::numeric_limits<int32_t>::max()),
+              "TestIsAbsoluteUint32#11");
+static_assert(IsAbsoluteUint<31, int32_t>(std::numeric_limits<int32_t>::max()),
+              "TestIsAbsoluteUint32#12");
+static_assert(!IsAbsoluteUint<31, int32_t>(std::numeric_limits<int32_t>::min()),
+              "TestIsAbsoluteUint32#13");
+static_assert(IsAbsoluteUint<31, int32_t>(std::numeric_limits<int32_t>::min() + 1),
+              "TestIsAbsoluteUint32#14");
+static_assert(IsAbsoluteUint<32, int32_t>(std::numeric_limits<int32_t>::max()),
+              "TestIsAbsoluteUint32#15");
+static_assert(IsAbsoluteUint<32, int32_t>(std::numeric_limits<int32_t>::min()),
+              "TestIsAbsoluteUint32#16");
+static_assert(IsAbsoluteUint<32, int32_t>(0), "TestIsAbsoluteUint32#17");
+
+static_assert(!IsAbsoluteUint<1, int64_t>(-2), "TestIsAbsoluteUint64#1");
+static_assert(IsAbsoluteUint<1, int64_t>(-1), "TestIsAbsoluteUint64#2");
+static_assert(IsAbsoluteUint<1, int64_t>(0), "TestIsAbsoluteUint64#3");
+static_assert(IsAbsoluteUint<1, int64_t>(1), "TestIsAbsoluteUint64#4");
+static_assert(!IsAbsoluteUint<1, int64_t>(2), "TestIsAbsoluteUint64#5");
+static_assert(!IsAbsoluteUint<4, int64_t>(-16), "TestIsAbsoluteUint64#6");
+static_assert(IsAbsoluteUint<4, int64_t>(-15), "TestIsAbsoluteUint64#7");
+static_assert(IsAbsoluteUint<4, int64_t>(0), "TestIsAbsoluteUint64#8");
+static_assert(IsAbsoluteUint<4, int64_t>(15), "TestIsAbsoluteUint64#9");
+static_assert(!IsAbsoluteUint<4, int64_t>(16), "TestIsAbsoluteUint64#10");
+static_assert(!IsAbsoluteUint<30, int64_t>(std::numeric_limits<int32_t>::max()),
+              "TestIsAbsoluteUint64#11");
+static_assert(IsAbsoluteUint<31, int64_t>(std::numeric_limits<int32_t>::max()),
+              "TestIsAbsoluteUint64#12");
+static_assert(!IsAbsoluteUint<31, int64_t>(std::numeric_limits<int32_t>::min()),
+              "TestIsAbsoluteUint64#13");
+static_assert(IsAbsoluteUint<31, int64_t>(std::numeric_limits<int32_t>::min() + 1),
+              "TestIsAbsoluteUint64#14");
+static_assert(IsAbsoluteUint<32, int64_t>(std::numeric_limits<int32_t>::max()),
+              "TestIsAbsoluteUint64#15");
+static_assert(IsAbsoluteUint<32, int64_t>(std::numeric_limits<int32_t>::min()),
+              "TestIsAbsoluteUint64#16");
+static_assert(!IsAbsoluteUint<62, int64_t>(std::numeric_limits<int64_t>::max()),
+              "TestIsAbsoluteUint64#17");
+static_assert(IsAbsoluteUint<63, int64_t>(std::numeric_limits<int64_t>::max()),
+              "TestIsAbsoluteUint64#18");
+static_assert(!IsAbsoluteUint<63, int64_t>(std::numeric_limits<int64_t>::min()),
+              "TestIsAbsoluteUint64#19");
+static_assert(IsAbsoluteUint<63, int64_t>(std::numeric_limits<int64_t>::min() + 1),
+              "TestIsAbsoluteUint64#20");
+static_assert(IsAbsoluteUint<64, int64_t>(std::numeric_limits<int64_t>::max()),
+              "TestIsAbsoluteUint64#21");
+static_assert(IsAbsoluteUint<64, int64_t>(std::numeric_limits<int64_t>::min()),
+              "TestIsAbsoluteUint64#22");
+static_assert(!IsAbsoluteUint<32, int64_t>(-kUint32MaxPlus1), "TestIsAbsoluteUint64#23");
+static_assert(IsAbsoluteUint<32, int64_t>(-kUint32MaxPlus1 + 1), "TestIsAbsoluteUint64#24");
+static_assert(IsAbsoluteUint<32, int64_t>(0), "TestIsAbsoluteUint64#25");
+static_assert(IsAbsoluteUint<64, int64_t>(0), "TestIsAbsoluteUint64#26");
+static_assert(IsAbsoluteUint<32, int64_t>(std::numeric_limits<uint32_t>::max()),
+              "TestIsAbsoluteUint64#27");
+static_assert(!IsAbsoluteUint<32, int64_t>(kUint32MaxPlus1), "TestIsAbsoluteUint64#28");
+
+template <typename Container>
+void CheckElements(const std::initializer_list<uint32_t>& expected, const Container& elements) {
+  auto expected_it = expected.begin();
+  auto element_it = elements.begin();
+  size_t idx = 0u;
+  while (expected_it != expected.end() && element_it != elements.end()) {
+    EXPECT_EQ(*expected_it, *element_it) << idx;
+    ++idx;
+    ++expected_it;
+    ++element_it;
+  }
+  ASSERT_TRUE(expected_it == expected.end() && element_it == elements.end())
+      << std::boolalpha << (expected_it == expected.end()) << " " << (element_it == elements.end());
+}
+
+TEST(BitUtilsTest, TestLowToHighBits32) {
+  CheckElements({}, LowToHighBits<uint32_t>(0u));
+  CheckElements({0}, LowToHighBits<uint32_t>(1u));
+  CheckElements({15}, LowToHighBits<uint32_t>(0x8000u));
+  CheckElements({31}, LowToHighBits<uint32_t>(0x80000000u));
+  CheckElements({0, 31}, LowToHighBits<uint32_t>(0x80000001u));
+  CheckElements({0, 1, 2, 3, 4, 5, 6, 7, 31}, LowToHighBits<uint32_t>(0x800000ffu));
+  CheckElements({0, 8, 16, 24, 31}, LowToHighBits<uint32_t>(0x81010101u));
+  CheckElements({16, 17, 30, 31}, LowToHighBits<uint32_t>(0xc0030000u));
+  CheckElements({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+                 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
+                LowToHighBits<uint32_t>(0xffffffffu));
+}
+
+TEST(BitUtilsTest, TestLowToHighBits64) {
+  CheckElements({}, LowToHighBits<uint64_t>(UINT64_C(0)));
+  CheckElements({0}, LowToHighBits<uint64_t>(UINT64_C(1)));
+  CheckElements({32}, LowToHighBits<uint64_t>(UINT64_C(0x100000000)));
+  CheckElements({63}, LowToHighBits<uint64_t>(UINT64_C(0x8000000000000000)));
+  CheckElements({0, 63}, LowToHighBits<uint64_t>(UINT64_C(0x8000000000000001)));
+  CheckElements({0, 1, 2, 3, 4, 5, 6, 7, 63},
+                LowToHighBits<uint64_t>(UINT64_C(0x80000000000000ff)));
+  CheckElements({0, 8, 16, 24, 32, 40, 48, 56, 63},
+                LowToHighBits<uint64_t>(UINT64_C(0x8101010101010101)));
+  CheckElements({16, 17, 62, 63}, LowToHighBits<uint64_t>(UINT64_C(0xc000000000030000)));
+  CheckElements({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+                 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+                 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+                 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63},
+                LowToHighBits<uint64_t>(UINT64_C(0xffffffffffffffff)));
+}
+
+TEST(BitUtilsTest, TestHighToLowBits32) {
+  CheckElements({}, HighToLowBits<uint32_t>(0u));
+  CheckElements({0}, HighToLowBits<uint32_t>(1u));
+  CheckElements({15}, HighToLowBits<uint32_t>(0x8000u));
+  CheckElements({31}, HighToLowBits<uint32_t>(0x80000000u));
+  CheckElements({31, 0}, HighToLowBits<uint32_t>(0x80000001u));
+  CheckElements({31, 7, 6, 5, 4, 3, 2, 1, 0}, HighToLowBits<uint32_t>(0x800000ffu));
+  CheckElements({31, 24, 16, 8, 0}, HighToLowBits<uint32_t>(0x81010101u));
+  CheckElements({31, 30, 17, 16}, HighToLowBits<uint32_t>(0xc0030000u));
+  CheckElements({31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
+                 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
+                HighToLowBits<uint32_t>(0xffffffffu));
+}
+
+TEST(BitUtilsTest, TestHighToLowBits64) {
+  CheckElements({}, HighToLowBits<uint64_t>(UINT64_C(0)));
+  CheckElements({0}, HighToLowBits<uint64_t>(UINT64_C(1)));
+  CheckElements({32}, HighToLowBits<uint64_t>(UINT64_C(0x100000000)));
+  CheckElements({63}, HighToLowBits<uint64_t>(UINT64_C(0x8000000000000000)));
+  CheckElements({63, 0}, HighToLowBits<uint64_t>(UINT64_C(0x8000000000000001)));
+  CheckElements({63, 7, 6, 5, 4, 3, 2, 1, 0},
+                HighToLowBits<uint64_t>(UINT64_C(0x80000000000000ff)));
+  CheckElements({63, 56, 48, 40, 32, 24, 16, 8, 0},
+                HighToLowBits<uint64_t>(UINT64_C(0x8101010101010101)));
+  CheckElements({63, 62, 17, 16}, HighToLowBits<uint64_t>(UINT64_C(0xc000000000030000)));
+  CheckElements({63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48,
+                 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32,
+                 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
+                 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
+                HighToLowBits<uint64_t>(UINT64_C(0xffffffffffffffff)));
+}
+
+}  // namespace art
diff --git a/runtime/base/bit_vector-inl.h b/runtime/base/bit_vector-inl.h
index 39b19e5..0887798 100644
--- a/runtime/base/bit_vector-inl.h
+++ b/runtime/base/bit_vector-inl.h
@@ -17,9 +17,9 @@
 #ifndef ART_RUNTIME_BASE_BIT_VECTOR_INL_H_
 #define ART_RUNTIME_BASE_BIT_VECTOR_INL_H_
 
+#include "base/bit_utils.h"
 #include "bit_vector.h"
 #include "logging.h"
-#include "utils.h"
 
 namespace art {
 
diff --git a/runtime/base/bit_vector.h b/runtime/base/bit_vector.h
index 6e4367a..17835f5 100644
--- a/runtime/base/bit_vector.h
+++ b/runtime/base/bit_vector.h
@@ -20,7 +20,7 @@
 #include <stdint.h>
 #include <iterator>
 
-#include "utils.h"
+#include "base/bit_utils.h"
 
 namespace art {
 
diff --git a/runtime/base/bounded_fifo.h b/runtime/base/bounded_fifo.h
index d04840a..7bcd382 100644
--- a/runtime/base/bounded_fifo.h
+++ b/runtime/base/bounded_fifo.h
@@ -17,16 +17,19 @@
 #ifndef ART_RUNTIME_BASE_BOUNDED_FIFO_H_
 #define ART_RUNTIME_BASE_BOUNDED_FIFO_H_
 
+#include "base/bit_utils.h"
+#include "base/logging.h"
+
 namespace art {
 
 // A bounded fifo is a fifo which has a bounded size. The power of two version uses a bit mask to
 // avoid needing to deal with wrapping integers around or using a modulo operation.
-template <typename T, const size_t MaxSize>
+template <typename T, const size_t kMaxSize>
 class BoundedFifoPowerOfTwo {
+  static_assert(IsPowerOfTwo(kMaxSize), "kMaxSize must be a power of 2.");
+
  public:
   BoundedFifoPowerOfTwo() {
-    // TODO: Do this with a compile time check.
-    CHECK(IsPowerOfTwo(MaxSize));
     clear();
   }
 
@@ -45,7 +48,7 @@
 
   void push_back(const T& value) {
     ++size_;
-    DCHECK_LE(size_, MaxSize);
+    DCHECK_LE(size_, kMaxSize);
     // Relies on integer overflow behavior.
     data_[back_index_++ & mask_] = value;
   }
@@ -61,9 +64,9 @@
   }
 
  private:
-  static const size_t mask_ = MaxSize - 1;
+  static const size_t mask_ = kMaxSize - 1;
   size_t back_index_, size_;
-  T data_[MaxSize];
+  T data_[kMaxSize];
 };
 
 }  // namespace art
diff --git a/runtime/base/histogram-inl.h b/runtime/base/histogram-inl.h
index 0f969b9..aba3762 100644
--- a/runtime/base/histogram-inl.h
+++ b/runtime/base/histogram-inl.h
@@ -17,15 +17,16 @@
 #ifndef ART_RUNTIME_BASE_HISTOGRAM_INL_H_
 #define ART_RUNTIME_BASE_HISTOGRAM_INL_H_
 
-#include "histogram.h"
-
-#include "utils.h"
-
 #include <algorithm>
 #include <cmath>
 #include <limits>
 #include <ostream>
 
+#include "histogram.h"
+
+#include "base/bit_utils.h"
+#include "base/time_utils.h"
+
 namespace art {
 
 template <class Value> inline void Histogram<Value>::AddValue(Value value) {
diff --git a/runtime/base/histogram.h b/runtime/base/histogram.h
index c312fb2..ef3a5d7 100644
--- a/runtime/base/histogram.h
+++ b/runtime/base/histogram.h
@@ -20,7 +20,6 @@
 #include <string>
 
 #include "base/logging.h"
-#include "utils.h"
 
 namespace art {
 
diff --git a/runtime/base/iteration_range.h b/runtime/base/iteration_range.h
new file mode 100644
index 0000000..6a0ef1f
--- /dev/null
+++ b/runtime/base/iteration_range.h
@@ -0,0 +1,54 @@
+/*
+ * 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_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
+// range [first, last) defined by two iterators.
+template <typename Iter>
+class IterationRange {
+ public:
+  typedef Iter iterator;
+  typedef typename std::iterator_traits<Iter>::difference_type difference_type;
+  typedef typename std::iterator_traits<Iter>::value_type value_type;
+  typedef typename std::iterator_traits<Iter>::pointer pointer;
+  typedef typename std::iterator_traits<Iter>::reference reference;
+
+  IterationRange(iterator first, iterator last) : first_(first), last_(last) { }
+
+  iterator begin() const { return first_; }
+  iterator end() const { return last_; }
+  iterator cbegin() const { return first_; }
+  iterator cend() const { return last_; }
+
+ private:
+  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/mutex-inl.h b/runtime/base/mutex-inl.h
index a727992..87840e7 100644
--- a/runtime/base/mutex-inl.h
+++ b/runtime/base/mutex-inl.h
@@ -25,6 +25,7 @@
 #include "base/value_object.h"
 #include "runtime.h"
 #include "thread.h"
+#include "utils.h"
 
 #if ART_USE_FUTEXES
 #include "linux/futex.h"
diff --git a/runtime/base/mutex.cc b/runtime/base/mutex.cc
index 99c7246..5c6065d 100644
--- a/runtime/base/mutex.cc
+++ b/runtime/base/mutex.cc
@@ -24,12 +24,12 @@
 
 #include "atomic.h"
 #include "base/logging.h"
+#include "base/time_utils.h"
 #include "base/value_object.h"
 #include "mutex-inl.h"
 #include "runtime.h"
 #include "scoped_thread_state_change.h"
 #include "thread-inl.h"
-#include "utils.h"
 
 namespace art {
 
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/base/time_utils.cc b/runtime/base/time_utils.cc
new file mode 100644
index 0000000..48b0a09
--- /dev/null
+++ b/runtime/base/time_utils.cc
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ */
+
+#include <inttypes.h>
+#include <sstream>
+
+#include "time_utils.h"
+
+#include "base/logging.h"
+#include "base/stringprintf.h"
+
+#if defined(__APPLE__)
+#include <sys/time.h>
+#endif
+
+namespace art {
+
+std::string PrettyDuration(uint64_t nano_duration, size_t max_fraction_digits) {
+  if (nano_duration == 0) {
+    return "0";
+  } else {
+    return FormatDuration(nano_duration, GetAppropriateTimeUnit(nano_duration),
+                          max_fraction_digits);
+  }
+}
+
+TimeUnit GetAppropriateTimeUnit(uint64_t nano_duration) {
+  const uint64_t one_sec = 1000 * 1000 * 1000;
+  const uint64_t one_ms  = 1000 * 1000;
+  const uint64_t one_us  = 1000;
+  if (nano_duration >= one_sec) {
+    return kTimeUnitSecond;
+  } else if (nano_duration >= one_ms) {
+    return kTimeUnitMillisecond;
+  } else if (nano_duration >= one_us) {
+    return kTimeUnitMicrosecond;
+  } else {
+    return kTimeUnitNanosecond;
+  }
+}
+
+uint64_t GetNsToTimeUnitDivisor(TimeUnit time_unit) {
+  const uint64_t one_sec = 1000 * 1000 * 1000;
+  const uint64_t one_ms  = 1000 * 1000;
+  const uint64_t one_us  = 1000;
+
+  switch (time_unit) {
+    case kTimeUnitSecond:
+      return one_sec;
+    case kTimeUnitMillisecond:
+      return one_ms;
+    case kTimeUnitMicrosecond:
+      return one_us;
+    case kTimeUnitNanosecond:
+      return 1;
+  }
+  return 0;
+}
+
+std::string FormatDuration(uint64_t nano_duration, TimeUnit time_unit,
+                           size_t max_fraction_digits) {
+  const char* unit = nullptr;
+  uint64_t divisor = GetNsToTimeUnitDivisor(time_unit);
+  switch (time_unit) {
+    case kTimeUnitSecond:
+      unit = "s";
+      break;
+    case kTimeUnitMillisecond:
+      unit = "ms";
+      break;
+    case kTimeUnitMicrosecond:
+      unit = "us";
+      break;
+    case kTimeUnitNanosecond:
+      unit = "ns";
+      break;
+  }
+  const uint64_t whole_part = nano_duration / divisor;
+  uint64_t fractional_part = nano_duration % divisor;
+  if (fractional_part == 0) {
+    return StringPrintf("%" PRIu64 "%s", whole_part, unit);
+  } else {
+    static constexpr size_t kMaxDigits = 30;
+    size_t avail_digits = kMaxDigits;
+    char fraction_buffer[kMaxDigits];
+    char* ptr = fraction_buffer;
+    uint64_t multiplier = 10;
+    // This infinite loops if fractional part is 0.
+    while (avail_digits > 1 && fractional_part * multiplier < divisor) {
+      multiplier *= 10;
+      *ptr++ = '0';
+      avail_digits--;
+    }
+    snprintf(ptr, avail_digits, "%" PRIu64, fractional_part);
+    fraction_buffer[std::min(kMaxDigits - 1, max_fraction_digits)] = '\0';
+    return StringPrintf("%" PRIu64 ".%s%s", whole_part, fraction_buffer, unit);
+  }
+}
+
+std::string GetIsoDate() {
+  time_t now = time(nullptr);
+  tm tmbuf;
+  tm* ptm = localtime_r(&now, &tmbuf);
+  return StringPrintf("%04d-%02d-%02d %02d:%02d:%02d",
+      ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday,
+      ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
+}
+
+uint64_t MilliTime() {
+#if defined(__linux__)
+  timespec now;
+  clock_gettime(CLOCK_MONOTONIC, &now);
+  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_nsec / UINT64_C(1000000);
+#else  // __APPLE__
+  timeval now;
+  gettimeofday(&now, nullptr);
+  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_usec / UINT64_C(1000);
+#endif
+}
+
+uint64_t MicroTime() {
+#if defined(__linux__)
+  timespec now;
+  clock_gettime(CLOCK_MONOTONIC, &now);
+  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_nsec / UINT64_C(1000);
+#else  // __APPLE__
+  timeval now;
+  gettimeofday(&now, nullptr);
+  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_usec;
+#endif
+}
+
+uint64_t NanoTime() {
+#if defined(__linux__)
+  timespec now;
+  clock_gettime(CLOCK_MONOTONIC, &now);
+  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec;
+#else  // __APPLE__
+  timeval now;
+  gettimeofday(&now, nullptr);
+  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_usec * UINT64_C(1000);
+#endif
+}
+
+uint64_t ThreadCpuNanoTime() {
+#if defined(__linux__)
+  timespec now;
+  clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
+  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec;
+#else  // __APPLE__
+  UNIMPLEMENTED(WARNING);
+  return -1;
+#endif
+}
+
+void NanoSleep(uint64_t ns) {
+  timespec tm;
+  tm.tv_sec = ns / MsToNs(1000);
+  tm.tv_nsec = ns - static_cast<uint64_t>(tm.tv_sec) * MsToNs(1000);
+  nanosleep(&tm, nullptr);
+}
+
+void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts) {
+  int64_t endSec;
+
+  if (absolute) {
+#if !defined(__APPLE__)
+    clock_gettime(clock, ts);
+#else
+    UNUSED(clock);
+    timeval tv;
+    gettimeofday(&tv, nullptr);
+    ts->tv_sec = tv.tv_sec;
+    ts->tv_nsec = tv.tv_usec * 1000;
+#endif
+  } else {
+    ts->tv_sec = 0;
+    ts->tv_nsec = 0;
+  }
+  endSec = ts->tv_sec + ms / 1000;
+  if (UNLIKELY(endSec >= 0x7fffffff)) {
+    std::ostringstream ss;
+    LOG(INFO) << "Note: end time exceeds epoch: " << ss.str();
+    endSec = 0x7ffffffe;
+  }
+  ts->tv_sec = endSec;
+  ts->tv_nsec = (ts->tv_nsec + (ms % 1000) * 1000000) + ns;
+
+  // Catch rollover.
+  if (ts->tv_nsec >= 1000000000L) {
+    ts->tv_sec++;
+    ts->tv_nsec -= 1000000000L;
+  }
+}
+
+}  // namespace art
diff --git a/runtime/base/time_utils.h b/runtime/base/time_utils.h
new file mode 100644
index 0000000..f58c22a
--- /dev/null
+++ b/runtime/base/time_utils.h
@@ -0,0 +1,89 @@
+/*
+ * 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_BASE_TIME_UTILS_H_
+#define ART_RUNTIME_BASE_TIME_UTILS_H_
+
+#include <stdint.h>
+#include <string>
+#include <time.h>
+
+#include "base/macros.h"
+
+namespace art {
+
+enum TimeUnit {
+  kTimeUnitNanosecond,
+  kTimeUnitMicrosecond,
+  kTimeUnitMillisecond,
+  kTimeUnitSecond,
+};
+
+// Returns a human-readable time string which prints every nanosecond while trying to limit the
+// number of trailing zeros. Prints using the largest human readable unit up to a second.
+// e.g. "1ms", "1.000000001s", "1.001us"
+std::string PrettyDuration(uint64_t nano_duration, size_t max_fraction_digits = 3);
+
+// Format a nanosecond time to specified units.
+std::string FormatDuration(uint64_t nano_duration, TimeUnit time_unit,
+                           size_t max_fraction_digits);
+
+// Get the appropriate unit for a nanosecond duration.
+TimeUnit GetAppropriateTimeUnit(uint64_t nano_duration);
+
+// Get the divisor to convert from a nanoseconds to a time unit.
+uint64_t GetNsToTimeUnitDivisor(TimeUnit time_unit);
+
+// Returns the current date in ISO yyyy-mm-dd hh:mm:ss format.
+std::string GetIsoDate();
+
+// Returns the monotonic time since some unspecified starting point in milliseconds.
+uint64_t MilliTime();
+
+// Returns the monotonic time since some unspecified starting point in microseconds.
+uint64_t MicroTime();
+
+// Returns the monotonic time since some unspecified starting point in nanoseconds.
+uint64_t NanoTime();
+
+// Returns the thread-specific CPU-time clock in nanoseconds or -1 if unavailable.
+uint64_t ThreadCpuNanoTime();
+
+// Converts the given number of nanoseconds to milliseconds.
+static constexpr inline uint64_t NsToMs(uint64_t ns) {
+  return ns / 1000 / 1000;
+}
+
+// Converts the given number of milliseconds to nanoseconds
+static constexpr inline uint64_t MsToNs(uint64_t ns) {
+  return ns * 1000 * 1000;
+}
+
+#if defined(__APPLE__)
+// No clocks to specify on OS/X, fake value to pass to routines that require a clock.
+#define CLOCK_REALTIME 0xebadf00d
+#endif
+
+// Sleep for the given number of nanoseconds, a bad way to handle contention.
+void NanoSleep(uint64_t ns);
+
+// Initialize a timespec to either a relative time (ms,ns), or to the absolute
+// time corresponding to the indicated clock value plus the supplied offset.
+void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts);
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_BASE_TIME_UTILS_H_
diff --git a/runtime/base/time_utils_test.cc b/runtime/base/time_utils_test.cc
new file mode 100644
index 0000000..c553f4e
--- /dev/null
+++ b/runtime/base/time_utils_test.cc
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#include "time_utils.h"
+
+#include "gtest/gtest.h"
+
+namespace art {
+
+TEST(TimeUtilsTest, PrettyDuration) {
+  const uint64_t one_sec = 1000000000;
+  const uint64_t one_ms  = 1000000;
+  const uint64_t one_us  = 1000;
+
+  EXPECT_EQ("1s", PrettyDuration(1 * one_sec));
+  EXPECT_EQ("10s", PrettyDuration(10 * one_sec));
+  EXPECT_EQ("100s", PrettyDuration(100 * one_sec));
+  EXPECT_EQ("1.001s", PrettyDuration(1 * one_sec + one_ms));
+  EXPECT_EQ("1.000001s", PrettyDuration(1 * one_sec + one_us, 6));
+  EXPECT_EQ("1.000000001s", PrettyDuration(1 * one_sec + 1, 9));
+  EXPECT_EQ("1.000s", PrettyDuration(1 * one_sec + one_us, 3));
+
+  EXPECT_EQ("1ms", PrettyDuration(1 * one_ms));
+  EXPECT_EQ("10ms", PrettyDuration(10 * one_ms));
+  EXPECT_EQ("100ms", PrettyDuration(100 * one_ms));
+  EXPECT_EQ("1.001ms", PrettyDuration(1 * one_ms + one_us));
+  EXPECT_EQ("1.000001ms", PrettyDuration(1 * one_ms + 1, 6));
+
+  EXPECT_EQ("1us", PrettyDuration(1 * one_us));
+  EXPECT_EQ("10us", PrettyDuration(10 * one_us));
+  EXPECT_EQ("100us", PrettyDuration(100 * one_us));
+  EXPECT_EQ("1.001us", PrettyDuration(1 * one_us + 1));
+
+  EXPECT_EQ("1ns", PrettyDuration(1));
+  EXPECT_EQ("10ns", PrettyDuration(10));
+  EXPECT_EQ("100ns", PrettyDuration(100));
+}
+
+TEST(TimeUtilsTest, TestSleep) {
+  auto start = NanoTime();
+  NanoSleep(MsToNs(1500));
+  EXPECT_GT(NanoTime() - start, MsToNs(1000));
+}
+
+}  // namespace art
diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc
index b6a2aaf..f1f6f9b 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -22,9 +22,10 @@
 #include "timing_logger.h"
 
 #include "base/logging.h"
-#include "thread-inl.h"
 #include "base/stl_util.h"
 #include "base/histogram-inl.h"
+#include "base/time_utils.h"
+#include "thread-inl.h"
 
 #include <cmath>
 #include <iomanip>
diff --git a/runtime/base/unix_file/random_access_file_test.h b/runtime/base/unix_file/random_access_file_test.h
index e7ace4c..91858c2 100644
--- a/runtime/base/unix_file/random_access_file_test.h
+++ b/runtime/base/unix_file/random_access_file_test.h
@@ -82,7 +82,7 @@
 
   void TestReadContent(const std::string& content, RandomAccessFile* file) {
     const int buf_size = content.size() + 10;
-    std::unique_ptr<char> buf(new char[buf_size]);
+    std::unique_ptr<char[]> buf(new char[buf_size]);
     // Can't read from a negative offset.
     ASSERT_EQ(-EINVAL, file->Read(buf.get(), 0, -123));
 
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 292f830..84da475 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -26,10 +26,14 @@
 #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"
 #include "base/unix_file/fd_file.h"
 #include "base/value_object.h"
 #include "class_linker-inl.h"
@@ -53,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"
@@ -93,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()
@@ -109,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;
 }
 
@@ -274,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());
@@ -321,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
@@ -336,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);
@@ -383,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());
@@ -399,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
@@ -445,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();
@@ -528,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.
 
@@ -578,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);
@@ -1026,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;
@@ -1057,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);
+        }
+      }
+    }
   }
 }
 
@@ -1068,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);
@@ -1112,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);
@@ -1153,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());
@@ -1184,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)) {
@@ -1352,7 +1425,6 @@
 }
 
 ClassLinker::~ClassLinker() {
-  mirror::ArtMethod::ResetClass();
   mirror::Class::ResetClass();
   mirror::Constructor::ResetClass();
   mirror::Field::ResetClass();
@@ -1375,48 +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_ == 8) {
-    fields = hs.NewHandle<mirror::Array>(mirror::LongArray::Alloc(self, dex_file.NumFieldIds()));
-  } else {
-    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();
 }
 
@@ -1429,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();
@@ -1439,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(
@@ -1748,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));
     }
   }
 
@@ -1815,8 +1879,8 @@
   // TODO: Use fast jobjects?
   auto interfaces = hs.NewHandle<mirror::ObjectArray<mirror::Class>>(nullptr);
 
-  mirror::Class* new_class = nullptr;
-  if (!LinkClass(self, descriptor, klass, interfaces, &new_class)) {
+  MutableHandle<mirror::Class> h_new_class = hs.NewHandle<mirror::Class>(nullptr);
+  if (!LinkClass(self, descriptor, klass, interfaces, &h_new_class)) {
     // Linking failed.
     if (!klass->IsErroneous()) {
       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
@@ -1824,10 +1888,8 @@
     return nullptr;
   }
   self->AssertNoPendingException();
-  CHECK(new_class != nullptr) << descriptor;
-  CHECK(new_class->IsResolved()) << descriptor;
-
-  Handle<mirror::Class> new_class_h(hs.NewHandle(new_class));
+  CHECK(h_new_class.Get() != nullptr) << descriptor;
+  CHECK(h_new_class->IsResolved()) << descriptor;
 
   // Instrumentation may have updated entrypoints for all methods of all
   // classes. However it could not update methods of this class while we
@@ -1838,7 +1900,7 @@
     // suspending all threads to update entrypoints while we are doing it
     // for this class.
     DCHECK_EQ(self->GetState(), kRunnable);
-    Runtime::Current()->GetInstrumentation()->InstallStubsForClass(new_class_h.Get());
+    Runtime::Current()->GetInstrumentation()->InstallStubsForClass(h_new_class.Get());
   }
 
   /*
@@ -1852,9 +1914,9 @@
    * The class has been prepared and resolved but possibly not yet verified
    * at this point.
    */
-  Dbg::PostClassPrepare(new_class_h.Get());
+  Dbg::PostClassPrepare(h_new_class.Get());
 
-  return new_class_h.Get();
+  return h_new_class.Get();
 }
 
 uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
@@ -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,16 +2772,24 @@
   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_);
   auto existing_it = class_table_.FindWithHash(std::make_pair(descriptor, klass->GetClassLoader()),
                                                hash);
-  if (existing_it == class_table_.end()) {
-    CHECK(klass->IsProxyClass());
-    return nullptr;
-  }
-
+  CHECK(existing_it != class_table_.end());
   mirror::Class* existing = existing_it->Read();
   CHECK_NE(existing, klass) << descriptor;
   CHECK(!existing->IsResolved()) << descriptor;
@@ -3078,7 +3125,7 @@
 
 void ClassLinker::EnsurePreverifiedMethods(Handle<mirror::Class> klass) {
   if (!klass->IsPreverified()) {
-    klass->SetPreverifiedFlagOnAllMethods();
+    klass->SetPreverifiedFlagOnAllMethods(image_pointer_size_);
     klass->SetPreverified();
   }
 }
@@ -3169,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) {
@@ -3206,15 +3253,11 @@
   }
 }
 
-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) {
   Thread* self = soa.Self();
-  StackHandleScope<9> hs(self);
+  StackHandleScope<10> hs(self);
   MutableHandle<mirror::Class> klass(hs.NewHandle(
       AllocClass(self, GetClassRoot(kJavaLangClass), sizeof(mirror::Class))));
   if (klass.Get() == nullptr) {
@@ -3228,9 +3271,17 @@
   klass->SetClassLoader(soa.Decode<mirror::ClassLoader*>(loader));
   DCHECK_EQ(klass->GetPrimitiveType(), Primitive::kPrimNot);
   klass->SetName(soa.Decode<mirror::String*>(name));
-  mirror::Class* proxy_class = GetClassRoot(kJavaLangReflectProxy);
-  klass->SetDexCache(proxy_class->GetDexCache());
+  klass->SetDexCache(GetClassRoot(kJavaLangReflectProxy)->GetDexCache());
   mirror::Class::SetStatus(klass, mirror::Class::kStatusIdx, self);
+  std::string descriptor(GetDescriptorForProxy(klass.Get()));
+  size_t hash = ComputeModifiedUtf8Hash(descriptor.c_str());
+
+  // Insert the class before loading the fields as the field roots
+  // (ArtField::declaring_class_) are only visited from the class
+  // table. There can't be any suspend points between inserting the
+  // class and setting the field arrays below.
+  mirror::Class* existing = InsertClass(descriptor.c_str(), klass.Get(), hash);
+  CHECK(existing == nullptr);
 
   // Instance fields are inherited, but we add a couple of static fields...
   const size_t num_fields = 2;
@@ -3252,72 +3303,66 @@
   throws_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
 
   // Proxies have 1 direct method, the constructor
-  {
-    mirror::ObjectArray<mirror::ArtMethod>* directs = AllocArtMethodArray(self, 1);
-    if (UNLIKELY(directs == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return nullptr;
-    }
-    klass->SetDirectMethods(directs);
-    mirror::ArtMethod* constructor = CreateProxyConstructor(self, klass, proxy_class);
-    if (UNLIKELY(constructor == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return nullptr;
-    }
-    klass->SetDirectMethod(0, constructor);
+  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();
-  {
-    mirror::ObjectArray<mirror::ArtMethod>* virtuals = AllocArtMethodArray(self,
-                                                                           num_virtual_methods);
-    if (UNLIKELY(virtuals == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return nullptr;
-    }
-    klass->SetVirtualMethods(virtuals);
+  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<1> hs2(self);
-    Handle<mirror::ArtMethod> prototype(hs2.NewHandle(h_methods->Get(i)->GetArtMethod()));
-    mirror::ArtMethod* clone = CreateProxyMethod(self, klass, prototype);
-    if (UNLIKELY(clone == nullptr)) {
-      CHECK(self->IsExceptionPending());  // OOME.
-      return nullptr;
-    }
-    klass->SetVirtualMethod(i, clone);
+    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);
   }
 
-  klass->SetSuperClass(proxy_class);  // The super class is java.lang.reflect.Proxy
-  mirror::Class::SetStatus(klass, mirror::Class::kStatusLoaded, self);  // Now effectively in the loaded state.
+  // The super class is java.lang.reflect.Proxy
+  klass->SetSuperClass(GetClassRoot(kJavaLangReflectProxy));
+  // Now effectively in the loaded state.
+  mirror::Class::SetStatus(klass, mirror::Class::kStatusLoaded, self);
   self->AssertNoPendingException();
 
-  std::string descriptor(GetDescriptorForProxy(klass.Get()));
-  mirror::Class* new_class = nullptr;
+  MutableHandle<mirror::Class> new_class = hs.NewHandle<mirror::Class>(nullptr);
   {
     // Must hold lock on object when resolved.
     ObjectLock<mirror::Class> resolution_lock(self, klass);
-    // Link the fields and virtual methods, creating vtable and iftables
-    Handle<mirror::ObjectArray<mirror::Class> > h_interfaces(
+    // 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(
         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);
       return nullptr;
     }
   }
-
   CHECK(klass->IsRetired());
-  CHECK_NE(klass.Get(), new_class);
-  klass.Assign(new_class);
+  CHECK_NE(klass.Get(), new_class.Get());
+  klass.Assign(new_class.Get());
 
-  CHECK_EQ(interfaces_sfield->GetDeclaringClass(), new_class);
+  CHECK_EQ(interfaces_sfield->GetDeclaringClass(), klass.Get());
   interfaces_sfield->SetObject<false>(klass.Get(),
                                       soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
-  CHECK_EQ(throws_sfield->GetDeclaringClass(), new_class);
+  CHECK_EQ(throws_sfield->GetDeclaringClass(), klass.Get());
   throws_sfield->SetObject<false>(klass.Get(),
       soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >*>(throws));
 
@@ -3330,15 +3375,16 @@
   // 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);
     }
 
-    mirror::String* decoded_name = soa.Decode<mirror::String*>(name);
+    StackHandleScope<1> hs2(self);
+    Handle<mirror::String> decoded_name = hs2.NewHandle(soa.Decode<mirror::String*>(name));
     std::string interfaces_field_name(StringPrintf("java.lang.Class[] %s.interfaces",
                                                    decoded_name->ToModifiedUtf8().c_str()));
     CHECK_EQ(PrettyField(klass->GetStaticField(0)), interfaces_field_name);
@@ -3352,9 +3398,6 @@
     CHECK_EQ(klass.Get()->GetThrows(),
              soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class>>*>(throws));
   }
-  mirror::Class* existing = InsertClass(descriptor.c_str(), klass.Get(),
-                                        ComputeModifiedUtf8Hash(descriptor.c_str()));
-  CHECK(existing == nullptr);
   return klass.Get();
 }
 
@@ -3365,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());
   {
@@ -3375,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;
       }
@@ -3387,75 +3430,60 @@
   UNREACHABLE();
 }
 
-
-mirror::ArtMethod* ClassLinker::CreateProxyConstructor(Thread* self,
-                                                       Handle<mirror::Class> klass,
-                                                       mirror::Class* proxy_class) {
-  // Create constructor for Proxy that must initialize h
-  mirror::ObjectArray<mirror::ArtMethod>* proxy_direct_methods =
-      proxy_class->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.
-  proxy_class->GetDexCache()->SetResolvedMethod(proxy_constructor->GetDexMethodIndex(),
-                                                proxy_constructor);
+  GetClassRoot(kJavaLangReflectProxy)->GetDexCache()->SetResolvedMethod(
+      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());
@@ -3463,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;
     }
@@ -3495,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,
@@ -3665,7 +3690,7 @@
     }
   }
 
-  mirror::ArtMethod* clinit = klass->FindClassInitializer();
+  ArtMethod* clinit = klass->FindClassInitializer(image_pointer_size_);
   if (clinit != nullptr) {
     CHECK(can_init_statics);
     JValue result;
@@ -3754,22 +3779,89 @@
   UNREACHABLE();
 }
 
+static void ThrowSignatureCheckResolveReturnTypeException(Handle<mirror::Class> klass,
+                                                          Handle<mirror::Class> super_klass,
+                                                          ArtMethod* method,
+                                                          ArtMethod* m)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(Thread::Current()->IsExceptionPending());
+  DCHECK(!m->IsProxyMethod());
+  const DexFile* dex_file = m->GetDexFile();
+  const DexFile::MethodId& method_id = dex_file->GetMethodId(m->GetDexMethodIndex());
+  const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
+  uint16_t return_type_idx = proto_id.return_type_idx_;
+  std::string return_type = PrettyType(return_type_idx, *dex_file);
+  std::string class_loader = PrettyTypeOf(m->GetDeclaringClass()->GetClassLoader());
+  ThrowWrappedLinkageError(klass.Get(),
+                           "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).c_str(),
+                           super_klass->IsInterface() ? "interface" : "superclass",
+                           PrettyDescriptor(super_klass.Get()).c_str(),
+                           return_type.c_str(), class_loader.c_str());
+}
+
+static void ThrowSignatureCheckResolveArgException(Handle<mirror::Class> klass,
+                                                   Handle<mirror::Class> super_klass,
+                                                   ArtMethod* method,
+                                                   ArtMethod* m,
+                                                   uint32_t index, uint32_t arg_type_idx)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(Thread::Current()->IsExceptionPending());
+  DCHECK(!m->IsProxyMethod());
+  const DexFile* dex_file = m->GetDexFile();
+  std::string arg_type = PrettyType(arg_type_idx, *dex_file);
+  std::string class_loader = PrettyTypeOf(m->GetDeclaringClass()->GetClassLoader());
+  ThrowWrappedLinkageError(klass.Get(),
+                           "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).c_str(),
+                           super_klass->IsInterface() ? "interface" : "superclass",
+                           PrettyDescriptor(super_klass.Get()).c_str(),
+                           index, arg_type.c_str(), class_loader.c_str());
+}
+
+static void ThrowSignatureMismatch(Handle<mirror::Class> klass,
+                                   Handle<mirror::Class> super_klass,
+                                   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).c_str(),
+                    super_klass->IsInterface() ? "interface" : "superclass",
+                    PrettyDescriptor(super_klass.Get()).c_str(),
+                    error_msg.c_str());
+}
+
 static bool HasSameSignatureWithDifferentClassLoaders(Thread* self,
-                                                      Handle<mirror::ArtMethod> method1,
-                                                      Handle<mirror::ArtMethod> method2,
-                                                      std::string* error_msg)
+                                                      Handle<mirror::Class> klass,
+                                                      Handle<mirror::Class> super_klass,
+                                                      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);
+      return false;
+    }
     mirror::Class* other_return_type = method2->GetReturnType();
-    // NOTE: return_type.Get() must be sequenced after method2->GetReturnType().
+    if (UNLIKELY(other_return_type == nullptr)) {
+      ThrowSignatureCheckResolveReturnTypeException(klass, super_klass, method1, method2);
+      return false;
+    }
     if (UNLIKELY(other_return_type != return_type.Get())) {
-      *error_msg = StringPrintf("Return types mismatch: %s(%p) vs %s(%p)",
-                                PrettyClassAndClassLoader(return_type.Get()).c_str(),
-                                return_type.Get(),
-                                PrettyClassAndClassLoader(other_return_type).c_str(),
-                                other_return_type);
+      ThrowSignatureMismatch(klass, super_klass, method1,
+                             StringPrintf("Return types mismatch: %s(%p) vs %s(%p)",
+                                          PrettyClassAndClassLoader(return_type.Get()).c_str(),
+                                          return_type.Get(),
+                                          PrettyClassAndClassLoader(other_return_type).c_str(),
+                                          other_return_type));
       return false;
     }
   }
@@ -3777,39 +3869,54 @@
   const DexFile::TypeList* types2 = method2->GetParameterTypeList();
   if (types1 == nullptr) {
     if (types2 != nullptr && types2->Size() != 0) {
-      *error_msg = StringPrintf("Type list mismatch with %s",
-                                PrettyMethod(method2.Get(), true).c_str());
+      ThrowSignatureMismatch(klass, super_klass, method1,
+                             StringPrintf("Type list mismatch with %s",
+                                          PrettyMethod(method2, true).c_str()));
       return false;
     }
     return true;
   } else if (UNLIKELY(types2 == nullptr)) {
     if (types1->Size() != 0) {
-      *error_msg = StringPrintf("Type list mismatch with %s",
-                                PrettyMethod(method2.Get(), true).c_str());
+      ThrowSignatureMismatch(klass, super_klass, method1,
+                             StringPrintf("Type list mismatch with %s",
+                                          PrettyMethod(method2, true).c_str()));
       return false;
     }
     return true;
   }
   uint32_t num_types = types1->Size();
   if (UNLIKELY(num_types != types2->Size())) {
-    *error_msg = StringPrintf("Type list mismatch with %s",
-                              PrettyMethod(method2.Get(), true).c_str());
+    ThrowSignatureMismatch(klass, super_klass, method1,
+                           StringPrintf("Type list mismatch with %s",
+                                        PrettyMethod(method2, true).c_str()));
     return false;
   }
   for (uint32_t i = 0; i < num_types; ++i) {
     StackHandleScope<1> hs(self);
+    uint32_t param_type_idx = types1->GetTypeItem(i).type_idx_;
     Handle<mirror::Class> param_type(hs.NewHandle(
-        method1->GetClassFromTypeIndex(types1->GetTypeItem(i).type_idx_, true)));
+        method1->GetClassFromTypeIndex(param_type_idx, true)));
+    if (UNLIKELY(param_type.Get() == nullptr)) {
+      ThrowSignatureCheckResolveArgException(klass, super_klass, method1,
+                                             method1, i, param_type_idx);
+      return false;
+    }
+    uint32_t other_param_type_idx = types2->GetTypeItem(i).type_idx_;
     mirror::Class* other_param_type =
-        method2->GetClassFromTypeIndex(types2->GetTypeItem(i).type_idx_, true);
-    // NOTE: param_type.Get() must be sequenced after method2->GetClassFromTypeIndex(...).
+        method2->GetClassFromTypeIndex(other_param_type_idx, true);
+    if (UNLIKELY(other_param_type == nullptr)) {
+      ThrowSignatureCheckResolveArgException(klass, super_klass, method1,
+                                             method2, i, other_param_type_idx);
+      return false;
+    }
     if (UNLIKELY(param_type.Get() != other_param_type)) {
-      *error_msg = StringPrintf("Parameter %u type mismatch: %s(%p) vs %s(%p)",
-                                i,
-                                PrettyClassAndClassLoader(param_type.Get()).c_str(),
-                                param_type.Get(),
-                                PrettyClassAndClassLoader(other_param_type).c_str(),
-                                other_param_type);
+      ThrowSignatureMismatch(klass, super_klass, method1,
+                             StringPrintf("Parameter %u type mismatch: %s(%p) vs %s(%p)",
+                                          i,
+                                          PrettyClassAndClassLoader(param_type.Get()).c_str(),
+                                          param_type.Get(),
+                                          PrettyClassAndClassLoader(other_param_type).c_str(),
+                                          other_param_type));
       return false;
     }
   }
@@ -3823,43 +3930,35 @@
   }
   // Begin with the methods local to the superclass.
   Thread* self = Thread::Current();
-  StackHandleScope<2> hs(self);
-  MutableHandle<mirror::ArtMethod> h_m(hs.NewHandle<mirror::ArtMethod>(nullptr));
-  MutableHandle<mirror::ArtMethod> super_h_m(hs.NewHandle<mirror::ArtMethod>(nullptr));
+  StackHandleScope<1> hs(self);
+  MutableHandle<mirror::Class> super_klass(hs.NewHandle<mirror::Class>(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()) {
-        std::string error_msg;
-        if (!HasSameSignatureWithDifferentClassLoaders(self, h_m, super_h_m, &error_msg)) {
-          ThrowLinkageError(klass.Get(),
-                            "Class %s method %s resolves differently in superclass %s: %s",
-                            PrettyDescriptor(klass.Get()).c_str(),
-                            PrettyMethod(h_m.Get()).c_str(),
-                            PrettyDescriptor(klass->GetSuperClass()).c_str(),
-                            error_msg.c_str());
+      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,
+                                                                m, super_m))) {
+          self->AssertPendingException();
           return false;
         }
       }
     }
   }
   for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
-    if (klass->GetClassLoader() != klass->GetIfTable()->GetInterface(i)->GetClassLoader()) {
-      uint32_t num_methods = klass->GetIfTable()->GetInterface(i)->NumVirtualMethods();
+    super_klass.Assign(klass->GetIfTable()->GetInterface(i));
+    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(klass->GetIfTable()->GetInterface(i)->GetVirtualMethod(j));
-        if (h_m.Get() != super_h_m.Get()) {
-          std::string error_msg;
-          if (!HasSameSignatureWithDifferentClassLoaders(self, h_m, super_h_m, &error_msg)) {
-            ThrowLinkageError(klass.Get(),
-                              "Class %s method %s resolves differently in interface %s: %s",
-                              PrettyDescriptor(klass.Get()).c_str(),
-                              PrettyMethod(h_m.Get()).c_str(),
-                              PrettyDescriptor(klass->GetIfTable()->GetInterface(i)).c_str(),
-                              error_msg.c_str());
+        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,
+                                                                  m, super_m))) {
+            self->AssertPendingException();
             return false;
           }
         }
@@ -3887,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);
@@ -3896,42 +3997,39 @@
   }
 
   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);
     }
   }
 }
 
 bool ClassLinker::LinkClass(Thread* self, const char* descriptor, Handle<mirror::Class> klass,
                             Handle<mirror::ObjectArray<mirror::Class>> interfaces,
-                            mirror::Class** new_class) {
+                            MutableHandle<mirror::Class>* h_new_class_out) {
   CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());
 
   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)) {
@@ -3950,31 +4048,28 @@
     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
     // class in the class_table_ during EnsureResolved.
     mirror::Class::SetStatus(klass, mirror::Class::kStatusResolved, self);
-    *new_class = klass.Get();
+    h_new_class_out->Assign(klass.Get());
   } else {
     CHECK(!klass->IsResolved());
     // Retire the temporary class and create the correctly sized resolved class.
-    *new_class = klass->CopyOf(self, class_size, &imt_handle_scope);
-    if (UNLIKELY(*new_class == nullptr)) {
-      CHECK(self->IsExceptionPending());  // Expect an OOME.
+    StackHandleScope<1> hs(self);
+    auto h_new_class = hs.NewHandle(klass->CopyOf(self, class_size, imt, image_pointer_size_));
+    if (UNLIKELY(h_new_class.Get() == nullptr)) {
+      self->AssertPendingOOMException();
       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
       return false;
     }
 
-    CHECK_EQ((*new_class)->GetClassSize(), class_size);
-    StackHandleScope<1> hs(self);
-    auto new_class_h = hs.NewHandleWrapper<mirror::Class>(new_class);
-    ObjectLock<mirror::Class> lock(self, new_class_h);
-
-    FixupTemporaryDeclaringClass(klass.Get(), new_class_h.Get());
-
-    mirror::Class* existing = UpdateClass(descriptor, new_class_h.Get(),
+    CHECK_EQ(h_new_class->GetClassSize(), class_size);
+    ObjectLock<mirror::Class> lock(self, h_new_class);
+    FixupTemporaryDeclaringClass(klass.Get(), h_new_class.Get());
+    mirror::Class* existing = UpdateClass(descriptor, h_new_class.Get(),
                                           ComputeModifiedUtf8Hash(descriptor));
     CHECK(existing == nullptr || existing == klass.Get());
 
@@ -3982,10 +4077,12 @@
     // class_table_ during EnsureResolved.
     mirror::Class::SetStatus(klass, mirror::Class::kStatusRetired, self);
 
-    CHECK_EQ(new_class_h->GetStatus(), mirror::Class::kStatusResolving);
+    CHECK_EQ(h_new_class->GetStatus(), mirror::Class::kStatusResolving);
     // This will notify waiters on new_class that saw the not yet resolved
     // class in the class_table_ during EnsureResolved.
-    mirror::Class::SetStatus(new_class_h, mirror::Class::kStatusResolved, self);
+    mirror::Class::SetStatus(h_new_class, mirror::Class::kStatusResolved, self);
+    // Return the new class.
+    h_new_class_out->Assign(h_new_class.Get());
   }
   return true;
 }
@@ -4276,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.
@@ -4286,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;
@@ -4299,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) {
@@ -4313,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();
@@ -4344,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.
@@ -4374,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;
         }
@@ -4398,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();
@@ -4410,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;
       }
     }
@@ -4457,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()) {
@@ -4480,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)
@@ -4492,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;
     }
@@ -4509,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;
       }
     }
@@ -4523,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);
@@ -4540,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();
@@ -4548,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.
@@ -4586,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) {
@@ -4635,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;
@@ -4649,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) {
@@ -4665,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);
@@ -4680,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
@@ -4746,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;
 }
 
@@ -4904,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) {
@@ -4979,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);
     }
   }
 
@@ -4999,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 *
@@ -5123,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.
@@ -5150,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;
@@ -5171,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.
@@ -5200,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;
         }
@@ -5234,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);
               }
@@ -5246,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);
               }
@@ -5258,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);
               }
@@ -5354,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();
@@ -5409,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());
@@ -5477,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;",
@@ -5555,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;
@@ -5666,7 +5845,7 @@
   ArtField* const parent_field =
       mirror::Class::FindField(self, hs.NewHandle(h_path_class_loader->GetClass()), "parent",
                                "Ljava/lang/ClassLoader;");
-  DCHECK(parent_field!= nullptr);
+  DCHECK(parent_field != nullptr);
   mirror::Object* boot_cl =
       soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader)->AllocObject(self);
   parent_field->SetObject<false>(h_path_class_loader.Get(), boot_cl);
@@ -5677,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 95c8aa0..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;
@@ -49,6 +50,7 @@
 }  // namespace mirror
 
 template<class T> class Handle;
+template<class T> class MutableHandle;
 class InternTable;
 template<class T> class ObjectLock;
 class Runtime;
@@ -70,13 +72,11 @@
     kJavaLangString,
     kJavaLangDexCache,
     kJavaLangRefReference,
-    kJavaLangReflectArtMethod,
     kJavaLangReflectConstructor,
     kJavaLangReflectField,
     kJavaLangReflectMethod,
     kJavaLangReflectProxy,
     kJavaLangStringArrayClass,
-    kJavaLangReflectArtMethodArrayClass,
     kJavaLangReflectConstructorArrayClass,
     kJavaLangReflectFieldArrayClass,
     kJavaLangReflectMethodArrayClass,
@@ -186,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
@@ -204,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)
@@ -224,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
@@ -262,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.
@@ -322,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_);
 
@@ -359,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)
@@ -380,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,
@@ -389,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.
@@ -429,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
@@ -443,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);
@@ -464,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.
@@ -472,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)
@@ -534,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_);
@@ -565,14 +569,13 @@
                                                 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,
                  Handle<mirror::ObjectArray<mirror::Class>> interfaces,
-                 mirror::Class** new_class)
+                 MutableHandle<mirror::Class>* h_new_class_out)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool LinkSuperClass(Handle<mirror::Class> klass)
@@ -583,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)
@@ -600,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_) {
@@ -622,11 +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,
-                                            mirror::Class* proxy_class)
+  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 b401066..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());
 }
 
@@ -269,6 +267,13 @@
   va_end(args);
 }
 
+void ThrowWrappedLinkageError(mirror::Class* referrer, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  ThrowWrappedException("Ljava/lang/LinkageError;", referrer, fmt, &args);
+  va_end(args);
+}
+
 // NegativeArraySizeException
 
 void ThrowNegativeArraySizeException(int size) {
@@ -310,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;
@@ -346,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();
@@ -356,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]);
@@ -383,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 49890e2..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, ...)
@@ -134,6 +134,10 @@
     __attribute__((__format__(__printf__, 2, 3)))
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
 
+void ThrowWrappedLinkageError(mirror::Class* referrer, const char* fmt, ...)
+    __attribute__((__format__(__printf__, 2, 3)))
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) COLD_ATTR;
+
 // NegativeArraySizeException
 
 void ThrowNegativeArraySizeException(int size)
@@ -171,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 0eb7f2b..24615e2 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -22,6 +22,8 @@
 
 #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"
 #include "dex_file-inl.h"
@@ -31,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"
@@ -77,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);
   }
@@ -183,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) {
@@ -201,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_);
   }
@@ -234,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()) {
@@ -260,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()) {
@@ -278,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)) {
@@ -307,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);
@@ -325,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]);
@@ -407,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) {
@@ -422,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_);
@@ -1394,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));
 }
 
@@ -1405,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();
 }
 
@@ -1424,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;
 }
 
@@ -1453,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_) {
@@ -1469,11 +1463,11 @@
 }
 
 std::string Dbg::GetMethodName(JDWP::MethodId method_id) {
-  mirror::ArtMethod* m = FromMethodId(method_id);
+  ArtMethod* m = FromMethodId(method_id);
   if (m == nullptr) {
     return "null";
   }
-  return m->GetName();
+  return m->GetInterfaceMethodIfProxy(sizeof(void*))->GetName();
 }
 
 std::string Dbg::GetFieldName(JDWP::FieldId field_id) {
@@ -1502,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) {
@@ -1524,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;
@@ -1590,14 +1584,18 @@
 
   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());
+    expandBufAddUtf8String(pReply, m->GetInterfaceMethodIfProxy(sizeof(void*))->GetName());
+    expandBufAddUtf8String(pReply,
+                           m->GetInterfaceMethodIfProxy(sizeof(void*))->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()));
   }
@@ -1634,7 +1632,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) {
@@ -1669,7 +1667,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;
@@ -1698,12 +1696,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);
@@ -1727,7 +1725,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);
 }
@@ -1741,7 +1739,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;
   }
@@ -2469,7 +2467,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;
@@ -2547,7 +2545,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) {
@@ -2710,7 +2708,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) {
@@ -2785,7 +2783,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) {
@@ -2796,7 +2794,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;
@@ -2806,10 +2804,30 @@
   JDWP::EventLocation location;
   SetEventLocation(&location, m, dex_pc);
 
+  // We need to be sure no exception is pending when calling JdwpState::PostLocationEvent.
+  // This is required to be able to call JNI functions to create JDWP ids. To achieve this,
+  // we temporarily clear the current thread's exception (if any) and will restore it after
+  // the call.
+  // Note: the only way to get a pending exception here is to suspend on a move-exception
+  // instruction.
+  Thread* const self = Thread::Current();
+  StackHandleScope<1> hs(self);
+  Handle<mirror::Throwable> pending_exception(hs.NewHandle(self->GetException()));
+  self->ClearException();
+  if (kIsDebugBuild && pending_exception.Get() != nullptr) {
+    const DexFile::CodeItem* code_item = location.method->GetCodeItem();
+    const Instruction* instr = Instruction::At(&code_item->insns_[location.dex_pc]);
+    CHECK_EQ(Instruction::MOVE_EXCEPTION, instr->Opcode());
+  }
+
   gJdwpState->PostLocationEvent(&location, this_object, event_flags, return_value);
+
+  if (pending_exception.Get() != nullptr) {
+    self->SetException(pending_exception.Get());
+  }
 }
 
-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;
@@ -2822,7 +2840,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()) {
@@ -2850,14 +2868,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.
@@ -2866,25 +2884,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.
       }
@@ -2892,12 +2908,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_) {
@@ -2915,10 +2931,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_;
 
@@ -2952,7 +2968,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;
@@ -3201,7 +3217,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) {
@@ -3211,19 +3227,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) {
@@ -3233,13 +3248,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) {
@@ -3268,7 +3283,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()) {
@@ -3332,7 +3347,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;
@@ -3367,7 +3382,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) {
@@ -3407,7 +3422,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.
@@ -3427,7 +3442,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.
@@ -3461,7 +3476,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;
@@ -3498,7 +3513,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;
@@ -3602,7 +3617,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) {
@@ -3618,7 +3633,7 @@
     }
 
     int stack_depth;
-    mirror::ArtMethod* method;
+    ArtMethod* method;
     int32_t line_number;
   };
 
@@ -3680,9 +3695,11 @@
     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;
-  if (!m->IsNative()) {
+  // 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).
+  if (m != nullptr && !m->IsNative()) {
     const DexFile::CodeItem* const code_item = m->GetCodeItem();
     DebugCallbackContext context(single_step_control, line_number, code_item);
     m->GetDexFile()->DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(),
@@ -3815,7 +3832,7 @@
       return error;
     }
 
-    mirror::ArtMethod* m = FromMethodId(method_id);
+    ArtMethod* m = FromMethodId(method_id);
     if (m->IsStatic() != (receiver == nullptr)) {
       return JDWP::ERR_INVALID_METHODID;
     }
@@ -3837,8 +3854,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();
@@ -3850,7 +3866,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;
@@ -3953,32 +3969,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());
@@ -4721,7 +4739,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());
@@ -4805,7 +4823,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;
       }
@@ -4861,7 +4879,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();
@@ -4934,7 +4952,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());
@@ -4996,7 +5014,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));
@@ -5024,12 +5042,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-inl.h b/runtime/dex_file-inl.h
index 760006a..4e6c3ca 100644
--- a/runtime/dex_file-inl.h
+++ b/runtime/dex_file-inl.h
@@ -17,11 +17,11 @@
 #ifndef ART_RUNTIME_DEX_FILE_INL_H_
 #define ART_RUNTIME_DEX_FILE_INL_H_
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "base/stringpiece.h"
 #include "dex_file.h"
 #include "leb128.h"
-#include "utils.h"
 
 namespace art {
 
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/elf_file.cc b/runtime/elf_file.cc
index b1d933d..9fd8c87 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1401,86 +1401,53 @@
 }
 
 template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta) {
+bool ElfFileImpl<ElfTypes>::FixupDebugSections(Elf_Addr base_address_delta) {
   if (base_address_delta == 0) {
     return true;
   }
-  if (FindSectionByName(".debug_frame") != nullptr) {
-    if (!ApplyOatPatchesTo(".debug_frame", base_address_delta)) {
-      return false;
-    }
-  }
-  if (FindSectionByName(".debug_info") != nullptr) {
-    if (!ApplyOatPatchesTo(".debug_info", base_address_delta)) {
-      return false;
-    }
-  }
-  if (FindSectionByName(".debug_line") != nullptr) {
-    if (!ApplyOatPatchesTo(".debug_line", base_address_delta)) {
-      return false;
-    }
-  }
-  return true;
+  return ApplyOatPatchesTo(".debug_frame", base_address_delta) &&
+         ApplyOatPatchesTo(".debug_info", base_address_delta) &&
+         ApplyOatPatchesTo(".debug_line", base_address_delta);
 }
 
 template <typename ElfTypes>
 bool ElfFileImpl<ElfTypes>::ApplyOatPatchesTo(
-    const char* target_section_name,
-    typename std::make_signed<Elf_Off>::type delta) {
-  auto patches_section = FindSectionByName(".oat_patches");
+    const char* target_section_name, Elf_Addr delta) {
+  auto target_section = FindSectionByName(target_section_name);
+  if (target_section == nullptr) {
+    return true;
+  }
+  std::string patches_name = target_section_name + std::string(".oat_patches");
+  auto patches_section = FindSectionByName(patches_name.c_str());
   if (patches_section == nullptr) {
-    LOG(ERROR) << ".oat_patches section not found.";
+    LOG(ERROR) << patches_name << " section not found.";
     return false;
   }
   if (patches_section->sh_type != SHT_OAT_PATCH) {
-    LOG(ERROR) << "Unexpected type of .oat_patches.";
+    LOG(ERROR) << "Unexpected type of " << patches_name;
     return false;
   }
-  auto target_section = FindSectionByName(target_section_name);
-  if (target_section == nullptr) {
-    LOG(ERROR) << target_section_name << " section not found.";
-    return false;
-  }
-  if (!ApplyOatPatches(
+  ApplyOatPatches(
       Begin() + patches_section->sh_offset,
       Begin() + patches_section->sh_offset + patches_section->sh_size,
-      target_section_name, delta,
+      delta,
       Begin() + target_section->sh_offset,
-      Begin() + target_section->sh_offset + target_section->sh_size)) {
-    LOG(ERROR) << target_section_name << " section not found in .oat_patches.";
-  }
+      Begin() + target_section->sh_offset + target_section->sh_size);
   return true;
 }
 
-// Apply .oat_patches to given section.
+// Apply LEB128 encoded patches to given section.
 template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::ApplyOatPatches(
-    const uint8_t* patches, const uint8_t* patches_end,
-    const char* target_section_name,
-    typename std::make_signed<Elf_Off>::type delta,
+void ElfFileImpl<ElfTypes>::ApplyOatPatches(
+    const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
     uint8_t* to_patch, const uint8_t* to_patch_end) {
-  // Read null-terminated section name.
-  const char* section_name;
-  while ((section_name = reinterpret_cast<const char*>(patches))[0] != '\0') {
-    patches += strlen(section_name) + 1;
-    uint32_t length = DecodeUnsignedLeb128(&patches);
-    const uint8_t* next_section = patches + length;
-    // Is it the section we want to patch?
-    if (strcmp(section_name, target_section_name) == 0) {
-      // Read LEB128 encoded list of advances.
-      while (patches < next_section) {
-        DCHECK_LT(patches, patches_end) << "Unexpected end of .oat_patches.";
-        to_patch += DecodeUnsignedLeb128(&patches);
-        DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of " << section_name;
-        // TODO: 32-bit vs 64-bit.  What is the right type to use here?
-        auto* patch_loc = reinterpret_cast<typename std::make_signed<Elf_Off>::type*>(to_patch);
-        *patch_loc += delta;
-      }
-      return true;
-    }
-    patches = next_section;
+  typedef __attribute__((__aligned__(1))) Elf_Addr UnalignedAddress;
+  while (patches < patches_end) {
+    to_patch += DecodeUnsignedLeb128(&patches);
+    DCHECK_LE(patches, patches_end) << "Unexpected end of patch list.";
+    DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of section.";
+    *reinterpret_cast<UnalignedAddress*>(to_patch) += delta;
   }
-  return false;
 }
 
 template <typename ElfTypes>
diff --git a/runtime/elf_file_impl.h b/runtime/elf_file_impl.h
index 3ad096f..0f466bd 100644
--- a/runtime/elf_file_impl.h
+++ b/runtime/elf_file_impl.h
@@ -119,12 +119,9 @@
   bool FixupProgramHeaders(Elf_Addr base_address);
   bool FixupSymbols(Elf_Addr base_address, bool dynamic);
   bool FixupRelocations(Elf_Addr base_address);
-  bool FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta);
-  bool ApplyOatPatchesTo(const char* target_section_name,
-                         typename std::make_signed<Elf_Off>::type base_address_delta);
-  static bool ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end,
-                              const char* target_section_name,
-                              typename std::make_signed<Elf_Off>::type delta,
+  bool FixupDebugSections(Elf_Addr base_address_delta);
+  bool ApplyOatPatchesTo(const char* target_section_name, Elf_Addr base_address_delta);
+  static void ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
                               uint8_t* to_patch, const uint8_t* to_patch_end);
 
   bool Strip(std::string* error_msg);
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 625e695..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,16 +38,55 @@
 
 namespace art {
 
-inline mirror::ArtMethod* GetCalleeSaveMethodCaller(StackReference<mirror::ArtMethod>* sp,
-                                                    Runtime::CalleeSaveType type,
-                                                    bool do_caller_check = false)
+inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method,
+                                    uint32_t method_index,
+                                    InvokeType invoke_type)
+  SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ArtMethod* caller = outer_method->GetDexCacheResolvedMethod(method_index, sizeof(void*));
+  if (!caller->IsRuntimeMethod()) {
+    return caller;
+  }
+
+  // The method in the dex cache can be the runtime method responsible for invoking
+  // the stub that will then update the dex cache. Therefore, we need to do the
+  // resolution ourselves.
+
+  StackHandleScope<2> hs(Thread::Current());
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  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_method->GetDexFile(), method_index, dex_cache, class_loader, nullptr, invoke_type);
+}
+
+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);
-  auto* caller = caller_sp->AsMirrorPtr();
+  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);
+    uintptr_t caller_pc = *reinterpret_cast<uintptr_t*>(
+        (reinterpret_cast<uint8_t*>(sp) + callee_return_pc_offset));
+    uintptr_t native_pc_offset = outer_method->NativeQuickPcOffset(caller_pc);
+    CodeInfo code_info = outer_method->GetOptimizedCodeInfo();
+    StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+    DCHECK(stack_map.IsValid());
+    if (stack_map.HasInlineInfo(code_info)) {
+      InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
+      uint32_t method_index = inline_info.GetMethodIndexAtDepth(inline_info.GetDepth() - 1);
+      InvokeType invoke_type = static_cast<InvokeType>(
+          inline_info.GetInvokeTypeAtDepth(inline_info.GetDepth() - 1));
+      caller = GetResolvedMethod(outer_method, method_index, invoke_type);
+    }
+  }
 
   if (kIsDebugBuild && do_caller_check) {
     // Note that do_caller_check is optional, as this method can be called by
@@ -60,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 */);
@@ -69,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)) {
@@ -150,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;
@@ -202,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);
@@ -238,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;
@@ -261,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);
@@ -283,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;
@@ -356,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); \
@@ -376,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.
@@ -429,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();
@@ -448,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);
@@ -482,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)
@@ -500,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)) {
@@ -539,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;
@@ -553,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;
   }
@@ -581,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)) {
@@ -629,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 8cd6ca6..7a44158 100644
--- a/runtime/entrypoints/quick/callee_save_frame.h
+++ b/runtime/entrypoints/quick/callee_save_frame.h
@@ -32,28 +32,28 @@
 #include "arch/x86_64/quick_method_frame_info_x86_64.h"
 
 namespace art {
-namespace mirror {
 class ArtMethod;
-}  // namespace mirror
 
 class ScopedQuickEntrypointChecks {
  public:
-  explicit ScopedQuickEntrypointChecks(Thread *self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : self_(self) {
-    if (kIsDebugBuild) {
+  explicit ScopedQuickEntrypointChecks(Thread *self,
+                                       bool entry_check = kIsDebugBuild,
+                                       bool exit_check = kIsDebugBuild)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : self_(self), exit_check_(exit_check) {
+    if (entry_check) {
       TestsOnEntry();
     }
   }
 
-  explicit ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : self_(kIsDebugBuild ? Thread::Current() : nullptr) {
+  ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : self_(kIsDebugBuild ? Thread::Current() : nullptr), exit_check_(kIsDebugBuild) {
     if (kIsDebugBuild) {
       TestsOnEntry();
     }
   }
 
   ~ScopedQuickEntrypointChecks() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    if (kIsDebugBuild) {
+    if (exit_check_) {
       TestsOnExit();
     }
   }
@@ -70,6 +70,7 @@
   }
 
   Thread* const self_;
+  bool exit_check_;
 };
 
 static constexpr size_t GetCalleeSaveFrameSize(InstructionSet isa, Runtime::CalleeSaveType type) {
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 eb1b105..2b5c15b 100644
--- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
@@ -14,22 +14,24 @@
  * 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)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ScopedQuickEntrypointChecks sqec(self);
+  // Instrumentation changes the stack. Thus, when exiting, the stack cannot be verified, so skip
+  // that part.
+  ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
   const void* result;
   if (instrumentation->IsDeoptimized(method)) {
@@ -45,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 345b0ad..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"
@@ -89,7 +89,7 @@
   // | LR         |
   // | X29        |
   // |  :         |
-  // | X19        |
+  // | X20        |
   // | X7         |
   // | :          |
   // | X1         |
@@ -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,33 +291,56 @@
     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 uint32_t GetCallingDexPc(StackReference<mirror::ArtMethod>* sp)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(sp->AsMirrorPtr()->IsCalleeSaveMethod());
-    return GetCallingMethod(sp)->ToDexPc(QuickArgumentVisitor::GetCallingPc(sp));
+  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<ArtMethod**>(previous_sp);
+  }
+
+  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);
+    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);
+
+    if (outer_method->IsOptimized(sizeof(void*))) {
+      CodeInfo code_info = outer_method->GetOptimizedCodeInfo();
+      StackMap stack_map = code_info.GetStackMapForNativePcOffset(outer_pc_offset);
+      DCHECK(stack_map.IsValid());
+      if (stack_map.HasInlineInfo(code_info)) {
+        InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
+        return inline_info.GetDexPcAtDepth(inline_info.GetDepth() - 1);
+      } else {
+        return stack_map.GetDexPc(code_info);
+      }
+    } else {
+      return outer_method->ToDexPc(outer_pc);
+    }
   }
 
   // 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),
@@ -328,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() {}
@@ -359,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.
@@ -544,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);
 }
@@ -552,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;
@@ -599,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.
@@ -621,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();
@@ -648,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);
@@ -663,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) {}
 
@@ -727,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);
@@ -737,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);
@@ -750,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();
@@ -763,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);
@@ -782,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;
@@ -818,12 +839,13 @@
 }
 
 // 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_) {
-  ScopedQuickEntrypointChecks sqec(self);
+  // 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
+  // does not have the same stack layout as the callee-save method).
+  ScopedQuickEntrypointChecks sqec(self, kIsDebugBuild, false);
   // Start new JNI local reference state
   JNIEnvExt* env = self->GetJniEnv();
   ScopedObjectAccessUnchecked soa(env);
@@ -835,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);
@@ -912,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())) {
@@ -923,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) << " "
@@ -953,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();
@@ -964,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*));
       }
     }
 
@@ -1013,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;
 }
 
@@ -1493,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);
 
@@ -1508,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;
   }
 
@@ -1535,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.
@@ -1552,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);
 
@@ -1643,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;
@@ -1661,7 +1683,7 @@
     sm_.AdvancePointer(self->GetJniEnv());
 
     if (is_static) {
-      sm_.AdvanceHandleScope((*sp)->AsMirrorPtr()->GetDeclaringClass());
+      sm_.AdvanceHandleScope((**sp)->GetDeclaringClass());
     }
   }
 
@@ -1817,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);
@@ -1893,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();
   }
 
@@ -1952,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;
@@ -1995,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);
@@ -2014,83 +2030,75 @@
 
 // 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(mirror::ArtMethod* interface_method,
+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);
-  mirror::ArtMethod* caller_method = QuickArgumentVisitor::GetCallingMethod(sp);
-  mirror::ArtMethod* method;
+  // 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.
+  ArtMethod* caller_method = QuickArgumentVisitor::GetOuterMethod(sp);
+  DCHECK_EQ(caller_method, QuickArgumentVisitor::GetCallingMethod(sp));
+  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 {
     DCHECK(interface_method == Runtime::Current()->GetResolutionMethod());
-
-    uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
-    const DexFile::CodeItem* code = caller_method->GetCodeItem();
-    CHECK_LT(dex_pc, code->insns_size_in_code_units_);
-    const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
-    Instruction::Code instr_code = instr->Opcode();
-    CHECK(instr_code == Instruction::INVOKE_INTERFACE ||
-          instr_code == Instruction::INVOKE_INTERFACE_RANGE)
-        << "Unexpected call into interface trampoline: " << instr->DumpString(nullptr);
-    uint32_t dex_method_idx;
-    if (instr_code == Instruction::INVOKE_INTERFACE) {
-      dex_method_idx = instr->VRegB_35c();
-    } else {
-      DCHECK_EQ(instr_code, Instruction::INVOKE_INTERFACE_RANGE);
-      dex_method_idx = instr->VRegB_3rc();
+    if (kIsDebugBuild) {
+      uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
+      const DexFile::CodeItem* code = caller_method->GetCodeItem();
+      CHECK_LT(dex_pc, code->insns_size_in_code_units_);
+      const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
+      Instruction::Code instr_code = instr->Opcode();
+      CHECK(instr_code == Instruction::INVOKE_INTERFACE ||
+            instr_code == Instruction::INVOKE_INTERFACE_RANGE)
+          << "Unexpected call into interface trampoline: " << instr->DumpString(nullptr);
+      if (instr_code == Instruction::INVOKE_INTERFACE) {
+        CHECK_EQ(dex_method_idx, instr->VRegB_35c());
+      } else {
+        CHECK_EQ(instr_code, Instruction::INVOKE_INTERFACE_RANGE);
+        CHECK_EQ(dex_method_idx, instr->VRegB_3rc());
+      }
     }
 
     const DexFile* dex_file = caller_method->GetDeclaringClass()->GetDexCache()
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/atomic_stack.h b/runtime/gc/accounting/atomic_stack.h
index 399832a..ac716ea 100644
--- a/runtime/gc/accounting/atomic_stack.h
+++ b/runtime/gc/accounting/atomic_stack.h
@@ -22,11 +22,11 @@
 #include <string>
 
 #include "atomic.h"
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "mem_map.h"
 #include "stack.h"
-#include "utils.h"
 
 namespace art {
 namespace gc {
diff --git a/runtime/gc/accounting/bitmap-inl.h b/runtime/gc/accounting/bitmap-inl.h
index e87a0c0..cd3923a 100644
--- a/runtime/gc/accounting/bitmap-inl.h
+++ b/runtime/gc/accounting/bitmap-inl.h
@@ -22,8 +22,8 @@
 #include <memory>
 
 #include "atomic.h"
+#include "base/bit_utils.h"
 #include "base/logging.h"
-#include "utils.h"
 
 namespace art {
 namespace gc {
diff --git a/runtime/gc/accounting/bitmap.cc b/runtime/gc/accounting/bitmap.cc
index 13fcdb3..fdded02 100644
--- a/runtime/gc/accounting/bitmap.cc
+++ b/runtime/gc/accounting/bitmap.cc
@@ -16,6 +16,7 @@
 
 #include "bitmap-inl.h"
 
+#include "base/bit_utils.h"
 #include "card_table.h"
 #include "mem_map.h"
 
diff --git a/runtime/gc/accounting/card_table-inl.h b/runtime/gc/accounting/card_table-inl.h
index b936d93..f72f219 100644
--- a/runtime/gc/accounting/card_table-inl.h
+++ b/runtime/gc/accounting/card_table-inl.h
@@ -18,11 +18,11 @@
 #define ART_RUNTIME_GC_ACCOUNTING_CARD_TABLE_INL_H_
 
 #include "atomic.h"
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "card_table.h"
 #include "mem_map.h"
 #include "space_bitmap.h"
-#include "utils.h"
 
 namespace art {
 namespace gc {
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/read_barrier_table.h b/runtime/gc/accounting/read_barrier_table.h
index bb9aae7..436df92 100644
--- a/runtime/gc/accounting/read_barrier_table.h
+++ b/runtime/gc/accounting/read_barrier_table.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_GC_ACCOUNTING_READ_BARRIER_TABLE_H_
 #define ART_RUNTIME_GC_ACCOUNTING_READ_BARRIER_TABLE_H_
 
+#include "base/bit_utils.h"
 #include "base/mutex.h"
 #include "gc/space/space.h"
 #include "globals.h"
diff --git a/runtime/gc/accounting/space_bitmap-inl.h b/runtime/gc/accounting/space_bitmap-inl.h
index ae91200..c16f5d3 100644
--- a/runtime/gc/accounting/space_bitmap-inl.h
+++ b/runtime/gc/accounting/space_bitmap-inl.h
@@ -22,8 +22,8 @@
 #include <memory>
 
 #include "atomic.h"
+#include "base/bit_utils.h"
 #include "base/logging.h"
-#include "utils.h"
 
 namespace art {
 namespace gc {
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/allocator/dlmalloc.cc b/runtime/gc/allocator/dlmalloc.cc
index 8558f96..3d85395 100644
--- a/runtime/gc/allocator/dlmalloc.cc
+++ b/runtime/gc/allocator/dlmalloc.cc
@@ -16,6 +16,7 @@
 
 #include "dlmalloc.h"
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 
 // ART specific morecore implementation defined in space.cc.
diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h
index a54edcc..0fcfe72 100644
--- a/runtime/gc/allocator/rosalloc.h
+++ b/runtime/gc/allocator/rosalloc.h
@@ -27,11 +27,11 @@
 #include <vector>
 
 #include "base/allocator.h"
+#include "base/bit_utils.h"
 #include "base/mutex.h"
 #include "base/logging.h"
 #include "globals.h"
 #include "thread.h"
-#include "utils.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/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc
index 47d6ada..afd0a30 100644
--- a/runtime/gc/collector/garbage_collector.cc
+++ b/runtime/gc/collector/garbage_collector.cc
@@ -25,11 +25,13 @@
 #include "base/histogram-inl.h"
 #include "base/logging.h"
 #include "base/mutex-inl.h"
+#include "base/time_utils.h"
 #include "gc/accounting/heap_bitmap.h"
 #include "gc/space/large_object_space.h"
 #include "gc/space/space-inl.h"
 #include "thread-inl.h"
 #include "thread_list.h"
+#include "utils.h"
 
 namespace art {
 namespace gc {
diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc
index 5401b56..91a0e8a 100644
--- a/runtime/gc/collector/mark_sweep.cc
+++ b/runtime/gc/collector/mark_sweep.cc
@@ -29,6 +29,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/mutex-inl.h"
+#include "base/time_utils.h"
 #include "base/timing_logger.h"
 #include "gc/accounting/card_table-inl.h"
 #include "gc/accounting/heap_bitmap-inl.h"
@@ -389,6 +390,9 @@
         ArtField* field = holder_->FindFieldByOffset(offset_);
         LOG(INTERNAL_FATAL) << "Field info: "
                             << " holder=" << holder_
+                            << " holder is "
+                            << (mark_sweep_->GetHeap()->IsLiveObjectLocked(holder_)
+                                ? "alive" : "dead")
                             << " holder_size=" << holder_size
                             << " holder_type=" << PrettyTypeOf(holder_)
                             << " offset=" << offset_.Uint32Value()
@@ -397,13 +401,20 @@
                             << (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()
                                 ? holder_->AsClass()->NumReferenceStaticFields()
                                 : holder_->GetClass()->NumReferenceInstanceFields())
                             << "\n";
+        // Print the memory content of the holder.
+        for (size_t i = 0; i < holder_size / sizeof(uint32_t); ++i) {
+          uint32_t* p = reinterpret_cast<uint32_t*>(holder_);
+          LOG(INTERNAL_FATAL) << &p[i] << ": " << "holder+" << (i * sizeof(uint32_t)) << " = "
+                              << std::hex << p[i];
+        }
       }
       PrintFileToLog("/proc/self/maps", LogSeverity::INTERNAL_FATAL);
       MemMap::DumpMaps(LOG(INTERNAL_FATAL), true);
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index fbf36e8..2d54330 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -19,6 +19,7 @@
 
 #include "heap.h"
 
+#include "base/time_utils.h"
 #include "debugger.h"
 #include "gc/accounting/card_table-inl.h"
 #include "gc/collector/semi_space.h"
@@ -29,8 +30,8 @@
 #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"
 
 namespace art {
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 11a0e3c..fbde494 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -28,6 +28,7 @@
 #include "base/dumpable.h"
 #include "base/histogram-inl.h"
 #include "base/stl_util.h"
+#include "base/time_utils.h"
 #include "common_throws.h"
 #include "cutils/sched_policy.h"
 #include "debugger.h"
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 90249f9..c72414a 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -24,6 +24,7 @@
 #include "allocator_type.h"
 #include "arch/instruction_set.h"
 #include "atomic.h"
+#include "base/time_utils.h"
 #include "base/timing_logger.h"
 #include "gc/accounting/atomic_stack.h"
 #include "gc/accounting/card_table.h"
diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc
index 01e8795..4d51d38 100644
--- a/runtime/gc/reference_processor.cc
+++ b/runtime/gc/reference_processor.cc
@@ -16,14 +16,16 @@
 
 #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"
 #include "ScopedLocalRef.h"
 #include "scoped_thread_state_change.h"
 #include "task_processor.h"
+#include "utils.h"
 #include "well_known_classes.h"
 
 namespace art {
diff --git a/runtime/gc/space/bump_pointer_space-inl.h b/runtime/gc/space/bump_pointer_space-inl.h
index 14a93d1..d9ad9a3 100644
--- a/runtime/gc/space/bump_pointer_space-inl.h
+++ b/runtime/gc/space/bump_pointer_space-inl.h
@@ -17,6 +17,7 @@
 #ifndef ART_RUNTIME_GC_SPACE_BUMP_POINTER_SPACE_INL_H_
 #define ART_RUNTIME_GC_SPACE_BUMP_POINTER_SPACE_INL_H_
 
+#include "base/bit_utils.h"
 #include "bump_pointer_space.h"
 
 namespace art {
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index 7b1a421f..5237c7b 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -16,6 +16,7 @@
 
 #include "dlmalloc_space-inl.h"
 
+#include "base/time_utils.h"
 #include "gc/accounting/card_table.h"
 #include "gc/accounting/space_bitmap-inl.h"
 #include "gc/heap.h"
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 99f5d45..437fd8c 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -23,12 +23,13 @@
 
 #include <random>
 
+#include "art_method.h"
 #include "base/macros.h"
 #include "base/stl_util.h"
-#include "base/unix_file/fd_file.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"
@@ -686,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,
@@ -696,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());
@@ -705,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;
@@ -728,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));
 
@@ -752,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/large_object_space.cc b/runtime/gc/space/large_object_space.cc
index 4dfdaa5..da4a930 100644
--- a/runtime/gc/space/large_object_space.cc
+++ b/runtime/gc/space/large_object_space.cc
@@ -27,7 +27,6 @@
 #include "os.h"
 #include "space-inl.h"
 #include "thread-inl.h"
-#include "utils.h"
 
 namespace art {
 namespace gc {
diff --git a/runtime/gc/space/large_object_space_test.cc b/runtime/gc/space/large_object_space_test.cc
index a261663..f04a7ca 100644
--- a/runtime/gc/space/large_object_space_test.cc
+++ b/runtime/gc/space/large_object_space_test.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "base/time_utils.h"
 #include "space_test.h"
 #include "large_object_space.h"
 
diff --git a/runtime/gc/space/rosalloc_space.cc b/runtime/gc/space/rosalloc_space.cc
index 2c7d93e..bc4414d 100644
--- a/runtime/gc/space/rosalloc_space.cc
+++ b/runtime/gc/space/rosalloc_space.cc
@@ -20,6 +20,7 @@
 #define ATRACE_TAG ATRACE_TAG_DALVIK
 #include "cutils/trace.h"
 
+#include "base/time_utils.h"
 #include "gc/accounting/card_table.h"
 #include "gc/accounting/space_bitmap-inl.h"
 #include "gc/heap.h"
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/gc/task_processor.cc b/runtime/gc/task_processor.cc
index ef34c68..a49121b 100644
--- a/runtime/gc/task_processor.cc
+++ b/runtime/gc/task_processor.cc
@@ -16,6 +16,7 @@
 
 #include "task_processor.h"
 
+#include "base/time_utils.h"
 #include "scoped_thread_state_change.h"
 
 namespace art {
diff --git a/runtime/gc/task_processor_test.cc b/runtime/gc/task_processor_test.cc
index 5dd6d8f..f06f68d 100644
--- a/runtime/gc/task_processor_test.cc
+++ b/runtime/gc/task_processor_test.cc
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
+#include "base/time_utils.h"
 #include "common_runtime_test.h"
 #include "task_processor.h"
 #include "thread_pool.h"
 #include "thread-inl.h"
-#include "utils.h"
 
 namespace art {
 namespace gc {
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 271312e..9a0e52e 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -23,7 +23,6 @@
 #include "base/macros.h"
 #include "handle.h"
 #include "stack.h"
-#include "utils.h"
 #include "verify_object.h"
 
 namespace art {
@@ -160,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/hprof/hprof.cc b/runtime/hprof/hprof.cc
index efead51..88a72ec 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -40,6 +40,7 @@
 #include "art_field-inl.h"
 #include "base/logging.h"
 #include "base/stringprintf.h"
+#include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
 #include "common_throws.h"
diff --git a/runtime/image.cc b/runtime/image.cc
index 2d8c1c4..947c914 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -16,35 +16,29 @@
 
 #include "image.h"
 
+#include "base/bit_utils.h"
 #include "mirror/object_array.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
-#include "utils.h"
 
 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 613414a..c6be7ef 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -21,10 +21,37 @@
 
 #include "globals.h"
 #include "mirror/object.h"
-#include "utils.h"
 
 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:
@@ -32,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;
@@ -55,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_;
   }
@@ -95,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_;
   }
@@ -109,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
@@ -146,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_;
 
@@ -180,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 34ab277..4b672e0 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -18,8 +18,10 @@
 
 #include "class_linker.h"
 #include "common_runtime_test.h"
+#include "dex_instruction.h"
 #include "handle.h"
 #include "handle_scope-inl.h"
+#include "interpreter/interpreter_common.h"
 #include "mirror/class_loader.h"
 #include "mirror/string-inl.h"
 #include "runtime.h"
@@ -50,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)            \
@@ -247,5 +249,33 @@
   ShadowFrame::DeleteDeoptimizedFrame(tmp);
 }
 
+TEST_F(UnstartedRuntimeTest, StringInit) {
+  Thread* self = Thread::Current();
+  ScopedObjectAccess soa(self);
+  mirror::Class* klass = mirror::String::GetJavaLangString();
+  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 };
+  const Instruction* inst = Instruction::At(inst_data);
+
+  JValue result;
+  ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, method, 0);
+  const char* base_string = "hello_world";
+  mirror::String* string_arg = mirror::String::AllocFromModifiedUtf8(self, base_string);
+  mirror::String* reference_empty_string = mirror::String::AllocFromModifiedUtf8(self, "");
+  shadow_frame->SetVRegReference(0, reference_empty_string);
+  shadow_frame->SetVRegReference(1, string_arg);
+
+  interpreter::DoCall<false, false>(method, self, *shadow_frame, inst, inst_data[0], &result);
+  mirror::String* string_result = reinterpret_cast<mirror::String*>(result.GetL());
+  EXPECT_EQ(string_arg->GetLength(), string_result->GetLength());
+  EXPECT_EQ(memcmp(string_arg->GetValue(), string_result->GetValue(),
+                   string_arg->GetLength() * sizeof(uint16_t)), 0);
+
+  ShadowFrame::DeleteDeoptimizedFrame(shadow_frame);
+}
+
 }  // namespace interpreter
 }  // namespace art
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index b795d72..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;
@@ -562,6 +562,11 @@
   return globals_.SynchronizedGet(self, &globals_lock_, ref);
 }
 
+void JavaVMExt::UpdateGlobal(Thread* self, IndirectRef ref, mirror::Object* result) {
+  WriterMutexLock mu(self, globals_lock_);
+  globals_.Update(ref, result);
+}
+
 mirror::Object* JavaVMExt::DecodeWeakGlobal(Thread* self, IndirectRef ref) {
   MutexLock mu(self, weak_globals_lock_);
   while (UNLIKELY(!allow_new_weak_globals_)) {
@@ -570,6 +575,11 @@
   return weak_globals_.Get(ref);
 }
 
+void JavaVMExt::UpdateWeakGlobal(Thread* self, IndirectRef ref, mirror::Object* result) {
+  MutexLock mu(self, weak_globals_lock_);
+  weak_globals_.Update(ref, result);
+}
+
 void JavaVMExt::DumpReferenceTables(std::ostream& os) {
   Thread* self = Thread::Current();
   {
@@ -727,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 deec6a9..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)
@@ -125,9 +125,17 @@
   mirror::Object* DecodeGlobal(Thread* self, IndirectRef ref)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  void UpdateGlobal(Thread* self, IndirectRef ref, mirror::Object* result)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      LOCKS_EXCLUDED(globals_lock_);
+
   mirror::Object* DecodeWeakGlobal(Thread* self, IndirectRef ref)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  void UpdateWeakGlobal(Thread* self, IndirectRef ref, mirror::Object* result)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      LOCKS_EXCLUDED(weak_globals_lock_);
+
   const JNIInvokeInterface* GetUncheckedFunctions() const {
     return unchecked_functions_;
   }
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/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc
index 8e9ab32..f7f70f6 100644
--- a/runtime/jdwp/jdwp_handler.cc
+++ b/runtime/jdwp/jdwp_handler.cc
@@ -32,6 +32,7 @@
 #include "jdwp/jdwp_priv.h"
 #include "runtime.h"
 #include "thread-inl.h"
+#include "utils.h"
 
 namespace art {
 
diff --git a/runtime/jdwp/jdwp_main.cc b/runtime/jdwp/jdwp_main.cc
index 5b30f0c..e6b97a2 100644
--- a/runtime/jdwp/jdwp_main.cc
+++ b/runtime/jdwp/jdwp_main.cc
@@ -22,6 +22,7 @@
 
 #include "atomic.h"
 #include "base/logging.h"
+#include "base/time_utils.h"
 #include "debugger.h"
 #include "jdwp/jdwp_priv.h"
 #include "scoped_thread_state_change.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 c698cfc..dbd8977 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -30,6 +30,7 @@
 
 namespace art {
 
+class ArtMethod;
 class CompilerCallbacks;
 struct RuntimeArgumentMap;
 
@@ -46,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();
@@ -75,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 2155552..cd123b9 100644
--- a/runtime/jit/jit_code_cache_test.cc
+++ b/runtime/jit/jit_code_cache_test.cc
@@ -16,12 +16,11 @@
 
 #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"
-#include "utils.h"
 
 namespace art {
 namespace jit {
@@ -51,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);
@@ -77,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/leb128.h b/runtime/leb128.h
index 2e27b8e..14683d4 100644
--- a/runtime/leb128.h
+++ b/runtime/leb128.h
@@ -17,8 +17,11 @@
 #ifndef ART_RUNTIME_LEB128_H_
 #define ART_RUNTIME_LEB128_H_
 
+#include <vector>
+
+#include "base/bit_utils.h"
+#include "base/logging.h"
 #include "globals.h"
-#include "utils.h"
 
 namespace art {
 
diff --git a/runtime/leb128_test.cc b/runtime/leb128_test.cc
index 87e13ff..1bb493d 100644
--- a/runtime/leb128_test.cc
+++ b/runtime/leb128_test.cc
@@ -18,6 +18,7 @@
 
 #include "gtest/gtest.h"
 #include "base/histogram-inl.h"
+#include "base/time_utils.h"
 
 namespace art {
 
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/lock_word.h b/runtime/lock_word.h
index 655aa3a..aafbfe4 100644
--- a/runtime/lock_word.h
+++ b/runtime/lock_word.h
@@ -20,9 +20,9 @@
 #include <iosfwd>
 #include <stdint.h>
 
+#include "base/bit_utils.h"
 #include "base/logging.h"
 #include "read_barrier.h"
-#include "utils.h"
 
 namespace art {
 namespace mirror {
diff --git a/runtime/memory_region.h b/runtime/memory_region.h
index 6a784eb..13c69ac 100644
--- a/runtime/memory_region.h
+++ b/runtime/memory_region.h
@@ -18,13 +18,15 @@
 #define ART_RUNTIME_MEMORY_REGION_H_
 
 #include <stdint.h>
+#include <type_traits>
 
+#include "arch/instruction_set.h"
+#include "base/bit_utils.h"
 #include "base/casts.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/value_object.h"
 #include "globals.h"
-#include "utils.h"
 
 namespace art {
 
@@ -71,7 +73,7 @@
   template<typename T>
   ALWAYS_INLINE T LoadUnaligned(uintptr_t offset) const {
     // Equivalent unsigned integer type corresponding to T.
-    typedef typename UnsignedIntegerType<sizeof(T)>::type U;
+    typedef typename std::make_unsigned<T>::type U;
     U equivalent_unsigned_integer_value = 0;
     // Read the value byte by byte in a little-endian fashion.
     for (size_t i = 0; i < sizeof(U); ++i) {
@@ -86,7 +88,7 @@
   template<typename T>
   ALWAYS_INLINE void StoreUnaligned(uintptr_t offset, T value) const {
     // Equivalent unsigned integer type corresponding to T.
-    typedef typename UnsignedIntegerType<sizeof(T)>::type U;
+    typedef typename std::make_unsigned<T>::type U;
     U equivalent_unsigned_integer_value = bit_cast<U, T>(value);
     // Write the value byte by byte in a little-endian fashion.
     for (size_t i = 0; i < sizeof(U); ++i) {
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 8b3418d..88d75ab 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -19,18 +19,20 @@
 
 #include "array.h"
 
+#include "base/bit_utils.h"
+#include "base/casts.h"
+#include "base/logging.h"
 #include "base/stringprintf.h"
-#include "class.h"
+#include "class-inl.h"
 #include "gc/heap-inl.h"
 #include "thread.h"
-#include "utils.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>
@@ -237,7 +239,7 @@
 }
 
 template<typename T>
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
 inline void PrimitiveArray<T>::SetWithoutChecks(int32_t i, T value) {
   if (kCheckTransaction) {
     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
@@ -245,7 +247,7 @@
   if (kTransactionActive) {
     Runtime::Current()->RecordWriteArray(this, i, GetWithoutChecks(i));
   }
-  DCHECK(CheckIsValidIndex(i));
+  DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
   GetData()[i] = value;
 }
 // Backward copy where elements are of aligned appropriately for T. Count is in T sized units.
@@ -369,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 832ad68..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_);
 
@@ -131,7 +133,9 @@
 
   // TODO fix thread safety analysis broken by the use of template. This should be
   // SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
-  template<bool kTransactionActive, bool kCheckTransaction = true>
+  template<bool kTransactionActive,
+           bool kCheckTransaction = true,
+           VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetWithoutChecks(int32_t i, T value) ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS;
 
   /*
@@ -174,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 cc6f5c4..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"
@@ -32,6 +33,7 @@
 #include "reference-inl.h"
 #include "runtime.h"
 #include "string.h"
+#include "utils.h"
 
 namespace art {
 namespace mirror {
@@ -59,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) {
@@ -339,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() {
@@ -405,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);
 }
@@ -498,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());
 }
@@ -593,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
@@ -628,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;
 }
 
@@ -650,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>();
@@ -811,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 d3cfd01..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,7 @@
 #include "object_callbacks.h"
 #include "primitive.h"
 #include "read_barrier_option.h"
+#include "stride_iterator.h"
 #include "utils.h"
 
 #ifndef IMT_SIZE
@@ -36,6 +38,7 @@
 namespace art {
 
 class ArtField;
+class ArtMethod;
 struct ClassOffsets;
 template<class T> class Handle;
 template<class T> class Handle;
@@ -45,7 +48,6 @@
 
 namespace mirror {
 
-class ArtMethod;
 class ClassLoader;
 class Constructor;
 class DexCache;
@@ -65,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
@@ -407,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>
@@ -428,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() {
@@ -470,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.
@@ -518,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,
@@ -674,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_) {
@@ -736,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_);
 
@@ -868,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_) {
@@ -887,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.
@@ -990,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.
@@ -1015,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_);
@@ -1038,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_);
@@ -1061,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_);
 
@@ -1086,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_);
 
@@ -1110,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_;
 
@@ -1124,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
@@ -1149,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.
@@ -1175,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_;
@@ -1190,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.
@@ -1202,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 1cb437e..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 == 8) {
-    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 == 8) {
-    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 933784e..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"
@@ -69,6 +70,7 @@
   mirror::DexCache* const dex_cache = declaring_class->GetDexCache();
   ArtField* const art_field = dex_cache->GetResolvedField(GetDexFieldIndex(), sizeof(void*));
   CHECK(art_field != nullptr);
+  CHECK_EQ(declaring_class, art_field->GetDeclaringClass());
   return art_field;
 }
 
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 39d0f56..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>
@@ -59,19 +60,23 @@
       OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass);
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline LockWord Object::GetLockWord(bool as_volatile) {
   if (as_volatile) {
-    return LockWord(GetField32Volatile(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+    return LockWord(GetField32Volatile<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
   }
-  return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
+  return LockWord(GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
 }
 
+template<VerifyObjectFlags kVerifyFlags>
 inline void Object::SetLockWord(LockWord new_val, bool as_volatile) {
   // Force use of non-transactional mode and do not check.
   if (as_volatile) {
-    SetField32Volatile<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
+    SetField32Volatile<false, false, kVerifyFlags>(
+        OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
   } else {
-    SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
+    SetField32<false, false, kVerifyFlags>(
+        OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
   }
 }
 
@@ -253,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();
@@ -292,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);
@@ -300,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());
@@ -333,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());
@@ -359,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());
@@ -950,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 5afe99f..f1c96b5 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() {
@@ -125,7 +125,9 @@
 
   // As_volatile can be false if the mutators are suspended. This is an optimization since it
   // avoids the barriers.
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   LockWord GetLockWord(bool as_volatile) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   void SetLockWord(LockWord new_val, bool as_volatile) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool CasLockWordWeakSequentiallyConsistent(LockWord old_val, LockWord new_val)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -176,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_);
 
@@ -196,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>
@@ -429,7 +435,7 @@
           field_offset, static_cast<int32_t>(ptr));
     } else {
       SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags>(
-          field_offset, static_cast<int64_t>(reinterpret_cast<intptr_t>(new_value)));
+          field_offset, static_cast<int64_t>(reinterpret_cast<uintptr_t>(new_value)));
     }
   }
   // TODO fix thread safety analysis broken by the use of template. This should be
@@ -463,8 +469,8 @@
     } else {
       int64_t v = GetField64<kVerifyFlags, kIsVolatile>(field_offset);
       // Check that we dont lose any non 0 bits.
-      DCHECK_EQ(reinterpret_cast<int64_t>(reinterpret_cast<T>(v)), v);
-      return reinterpret_cast<T>(v);
+      DCHECK_EQ(static_cast<int64_t>(static_cast<uintptr_t>(v)), v);
+      return reinterpret_cast<T>(static_cast<uintptr_t>(v));
     }
   }
 
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index d473816..bef4af6 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -17,6 +17,8 @@
 #ifndef ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
 #define ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
 
+#include <string>
+
 #include "object_array.h"
 
 #include "array-inl.h"
@@ -26,7 +28,7 @@
 #include "runtime.h"
 #include "handle_scope-inl.h"
 #include "thread.h"
-#include <string>
+#include "utils.h"
 
 namespace art {
 namespace mirror {
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 cd5d2f6..9f6cd11 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -25,13 +25,14 @@
 #include "string.h"
 #include "thread.h"
 #include "utf.h"
+#include "utils.h"
 
 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..1c21edb 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -71,9 +71,18 @@
 
 int32_t Throwable::GetStackDepth() {
   Object* stack_state = GetStackState();
-  if (stack_state == nullptr || !stack_state->IsObjectArray()) return -1;
-  ObjectArray<Object>* method_trace = down_cast<ObjectArray<Object>*>(stack_state);
-  return method_trace->GetLength() - 1;
+  if (stack_state == nullptr) {
+    return -1;
+  }
+  if (!stack_state->IsIntArray() && !stack_state->IsLongArray()) {
+    return -1;
+  }
+  mirror::PointerArray* method_trace = down_cast<mirror::PointerArray*>(stack_state->AsArray());
+  int32_t array_len = method_trace->GetLength();
+  // The format is [method pointers][pcs] so the depth is half the length (see method
+  // BuildInternalStackTraceVisitor::Init).
+  CHECK_EQ(array_len % 2, 0);
+  return array_len / 2;
 }
 
 std::string Throwable::Dump() {
@@ -86,17 +95,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 +121,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 4b41225..4be25d6 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -21,13 +21,14 @@
 #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"
 #include "class_linker.h"
 #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"
@@ -244,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_;
@@ -448,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;
@@ -993,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;
@@ -1086,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/monitor_test.cc b/runtime/monitor_test.cc
index 30cb2d8..2a29c60 100644
--- a/runtime/monitor_test.cc
+++ b/runtime/monitor_test.cc
@@ -20,6 +20,7 @@
 #include <string>
 
 #include "atomic.h"
+#include "base/time_utils.h"
 #include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "handle_scope-inl.h"
@@ -27,7 +28,6 @@
 #include "mirror/string-inl.h"  // Strings are easiest to allocate
 #include "scoped_thread_state_change.h"
 #include "thread_pool.h"
-#include "utils.h"
 
 namespace art {
 
diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc
index 46881b0..1078492 100644
--- a/runtime/native/dalvik_system_VMDebug.cc
+++ b/runtime/native/dalvik_system_VMDebug.cc
@@ -22,6 +22,7 @@
 #include <sstream>
 
 #include "base/histogram-inl.h"
+#include "base/time_utils.h"
 #include "class_linker.h"
 #include "common_throws.h"
 #include "debugger.h"
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 9736e15..5dd354d 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -16,6 +16,9 @@
 
 #include "dalvik_system_VMRuntime.h"
 
+#ifdef HAVE_ANDROID_OS
+extern "C" void android_set_application_target_sdk_version(uint32_t version);
+#endif
 #include <limits.h>
 #include <ScopedUtfChars.h>
 
@@ -24,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"
@@ -37,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"
@@ -192,6 +195,12 @@
   // Note that targetSdkVersion may be CUR_DEVELOPMENT (10000).
   // Note that targetSdkVersion may be 0, meaning "current".
   Runtime::Current()->SetTargetSdkVersion(target_sdk_version);
+
+#ifdef HAVE_ANDROID_OS
+  // This part is letting libc/dynamic linker know about current app's
+  // target sdk version to enable compatibility workarounds.
+  android_set_application_target_sdk_version(static_cast<uint32_t>(target_sdk_version));
+#endif
 }
 
 static void VMRuntime_registerNativeAllocation(JNIEnv* env, jobject, jint bytes) {
@@ -341,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;
   }
@@ -354,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;
@@ -371,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 {
@@ -443,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/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 1a7a3e5..1d06706 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -65,7 +65,7 @@
     DEBUG_ENABLE_SAFEMODE           = 1 << 3,
     DEBUG_ENABLE_JNI_LOGGING        = 1 << 4,
     DEBUG_ENABLE_JIT                = 1 << 5,
-    DEBUG_GENERATE_CFI              = 1 << 6,
+    DEBUG_GENERATE_DEBUG_INFO       = 1 << 6,
   };
 
   Runtime* const runtime = Runtime::Current();
@@ -112,10 +112,10 @@
   }
   runtime->GetJITOptions()->SetUseJIT(use_jit);
 
-  const bool generate_cfi = (debug_flags & DEBUG_GENERATE_CFI) != 0;
-  if (generate_cfi) {
-    runtime->AddCompilerOption("--include-cfi");
-    debug_flags &= ~DEBUG_GENERATE_CFI;
+  const bool generate_debug_info = (debug_flags & DEBUG_GENERATE_DEBUG_INFO) != 0;
+  if (generate_debug_info) {
+    runtime->AddCompilerOption("--generate-debug-info");
+    debug_flags &= ~DEBUG_GENERATE_DEBUG_INFO;
   }
 
   // This is for backwards compatibility with Dalvik.
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 721b7a3..ba898c6 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -21,11 +21,11 @@
 #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"
 #include "scoped_fast_native_object_access.h"
+#include "utils.h"
 
 namespace art {
 
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 b7f31f2..46cc5aa 100644
--- a/runtime/native_bridge_art_interface.cc
+++ b/runtime/native_bridge_art_interface.cc
@@ -16,42 +16,40 @@
 
 #include "native_bridge_art_interface.h"
 
+#include <signal.h>
+
 #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"
 
 namespace art {
 
 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;
 }
@@ -65,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);
       }
     }
   }
@@ -127,7 +123,19 @@
 }
 
 void InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
-  android::InitializeNativeBridge(env, instruction_set);
+  if (android::InitializeNativeBridge(env, instruction_set)) {
+    if (android::NativeBridgeGetVersion() >= 2U) {
+#ifdef _NSIG  // Undefined on Apple, but we don't support running on Mac, anyways.
+      // Managed signal handling support added in version 2.
+      for (int signal = 0; signal < _NSIG; ++signal) {
+        android::NativeBridgeSignalHandlerFn fn = android::NativeBridgeGetSignalHandler(signal);
+        if (fn != nullptr) {
+          SetSpecialSignalHandlerFn(signal, fn);
+        }
+      }
+#endif
+    }
+  }
 }
 
 void UnloadNativeBridge() {
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.cc b/runtime/oat.cc
index 4f6aabc..1dd2aad 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -20,8 +20,8 @@
 #include <zlib.h>
 
 #include "arch/instruction_set_features.h"
+#include "base/bit_utils.h"
 #include "base/stringprintf.h"
-#include "utils.h"
 
 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 3b0e6c1..87b0d43 100644
--- a/runtime/profiler.cc
+++ b/runtime/profiler.cc
@@ -22,14 +22,15 @@
 
 #include <fstream>
 
+#include "art_method-inl.h"
 #include "base/stl_util.h"
+#include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
 #include "common_throws.h"
 #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"
@@ -39,6 +40,7 @@
 #include "ScopedLocalRef.h"
 #include "thread.h"
 #include "thread_list.h"
+#include "utils.h"
 
 #include "entrypoints/quick/quick_entrypoints.h"
 
@@ -55,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),
@@ -64,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;
     }
@@ -79,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_;
 };
@@ -92,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;
@@ -400,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.
@@ -435,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);
@@ -448,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);
   }
@@ -464,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),
@@ -482,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) {
@@ -517,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;
@@ -577,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();
@@ -709,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-inl.h b/runtime/read_barrier-inl.h
index 5631ff4..d341ee1 100644
--- a/runtime/read_barrier-inl.h
+++ b/runtime/read_barrier-inl.h
@@ -24,6 +24,7 @@
 #include "mirror/object_reference.h"
 #include "mirror/reference.h"
 #include "runtime.h"
+#include "utils.h"
 
 namespace art {
 
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 d321d27..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.
@@ -464,7 +460,7 @@
   InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
   if (is_string_init) {
     // For string init, remap original receiver to StringFactory result.
-    soa.Self()->GetJniEnv()->locals.Update(obj, result.GetL());
+    UpdateReference(soa.Self(), obj, result.GetL());
   }
   return result;
 }
@@ -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.
@@ -494,7 +490,7 @@
   InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
   if (is_string_init) {
     // For string init, remap original receiver to StringFactory result.
-    soa.Self()->GetJniEnv()->locals.Update(obj, result.GetL());
+    UpdateReference(soa.Self(), obj, result.GetL());
   }
   return result;
 }
@@ -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.
@@ -525,7 +521,7 @@
   InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
   if (is_string_init) {
     // For string init, remap original receiver to StringFactory result.
-    soa.Self()->GetJniEnv()->locals.Update(obj, result.GetL());
+    UpdateReference(soa.Self(), obj, result.GetL());
   }
   return result;
 }
@@ -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.
@@ -556,7 +552,7 @@
   InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
   if (is_string_init) {
     // For string init, remap original receiver to StringFactory result.
-    soa.Self()->GetJniEnv()->locals.Update(obj, result.GetL());
+    UpdateReference(soa.Self(), obj, result.GetL());
   }
   return result;
 }
@@ -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;
   }
@@ -882,4 +877,21 @@
                                              actual_class_name.c_str()).c_str());
 }
 
+// This only works if there's one reference which points to the object in obj.
+// Will need to be fixed if there's cases where it's not.
+void UpdateReference(Thread* self, jobject obj, mirror::Object* result) {
+  IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
+  IndirectRefKind kind = GetIndirectRefKind(ref);
+  if (kind == kLocal) {
+    self->GetJniEnv()->locals.Update(obj, result);
+  } else if (kind == kHandleScopeOrInvalid) {
+    LOG(FATAL) << "Unsupported UpdateReference for kind kHandleScopeOrInvalid";
+  } else if (kind == kGlobal) {
+    self->GetJniEnv()->vm->UpdateGlobal(self, ref, result);
+  } else {
+    DCHECK_EQ(kind, kWeakGlobal);
+    self->GetJniEnv()->vm->UpdateWeakGlobal(self, ref, result);
+  }
+}
+
 }  // namespace art
diff --git a/runtime/reflection.h b/runtime/reflection.h
index 6b5ffc7..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;
@@ -85,6 +85,9 @@
 void InvalidReceiverError(mirror::Object* o, mirror::Class* c)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+void UpdateReference(Thread* self, jobject obj, mirror::Object* result)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_REFLECTION_H_
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..65ea77a 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);
@@ -1329,6 +1329,24 @@
   mirror::PrimitiveArray<int32_t>::VisitRoots(visitor);   // IntArray
   mirror::PrimitiveArray<int64_t>::VisitRoots(visitor);   // LongArray
   mirror::PrimitiveArray<int16_t>::VisitRoots(visitor);   // ShortArray
+  // Visiting the roots of these ArtMethods is not currently required since all the GcRoots are
+  // null.
+  BufferedRootVisitor<16> buffered_visitor(visitor, RootInfo(kRootVMInternal));
+  if (HasResolutionMethod()) {
+    resolution_method_->VisitRoots(buffered_visitor);
+  }
+  if (HasImtConflictMethod()) {
+    imt_conflict_method_->VisitRoots(buffered_visitor);
+  }
+  if (imt_unimplemented_method_ != nullptr) {
+    imt_unimplemented_method_->VisitRoots(buffered_visitor);
+  }
+  for (size_t i = 0; i < kLastCalleeSaveType; ++i) {
+    auto* m = reinterpret_cast<ArtMethod*>(callee_save_methods_[i]);
+    if (m != nullptr) {
+      m->VisitRoots(buffered_visitor);
+    }
+  }
 }
 
 void Runtime::VisitConcurrentRoots(RootVisitor* visitor, VisitRootFlags flags) {
@@ -1350,17 +1368,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 +1409,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 +1505,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 +1531,6 @@
   preinitialization_transaction_ = nullptr;
 }
 
-
 bool Runtime::IsTransactionAborted() const {
   if (!IsActiveTransaction()) {
     return false;
@@ -1709,4 +1689,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/runtime_linux.cc b/runtime/runtime_linux.cc
index d65e18e..f0b3c4e 100644
--- a/runtime/runtime_linux.cc
+++ b/runtime/runtime_linux.cc
@@ -340,6 +340,9 @@
                       << "Thread: " << tid << " \"" << thread_name << "\"\n"
                       << "Registers:\n" << Dumpable<UContext>(thread_context) << "\n"
                       << "Backtrace:\n" << Dumpable<Backtrace>(thread_backtrace);
+  if (kIsDebugBuild && signal_number == SIGSEGV) {
+    PrintFileToLog("/proc/self/maps", LogSeverity::INTERNAL_FATAL);
+  }
   Runtime* runtime = Runtime::Current();
   if (runtime != nullptr) {
     if (IsTimeoutSignal(signal_number)) {
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/signal_catcher.cc b/runtime/signal_catcher.cc
index 863d59b..9f8c55c 100644
--- a/runtime/signal_catcher.cc
+++ b/runtime/signal_catcher.cc
@@ -28,6 +28,7 @@
 #include <sstream>
 
 #include "arch/instruction_set.h"
+#include "base/time_utils.h"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
 #include "gc/heap.h"
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 6795516..4110887 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -17,12 +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"
@@ -34,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()) {
@@ -49,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 {
@@ -104,28 +109,31 @@
   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);
+  DCHECK(stack_map.IsValid());
   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) {
     if (IsInInlinedFrame()) {
       size_t depth_in_stack_map = current_inlining_depth_ - 1;
-      return GetCurrentQuickFrame()->AsMirrorPtr()->GetDexCacheResolvedMethod(
-          GetCurrentInlineInfo().GetMethodIndexAtDepth(depth_in_stack_map));
+      InlineInfo inline_info = GetCurrentInlineInfo();
+      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(), 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 {
@@ -143,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()) {
@@ -186,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;
@@ -213,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());
@@ -230,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);
@@ -253,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();
@@ -262,13 +270,14 @@
   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();
 
   uint32_t native_pc_offset = outer_method->NativeQuickPcOffset(cur_quick_frame_pc_);
   StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+  DCHECK(stack_map.IsValid());
   size_t depth_in_stack_map = current_inlining_depth_ - 1;
 
   DexRegisterMap dex_register_map = IsInInlinedFrame()
@@ -326,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);
@@ -351,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);
@@ -378,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;
@@ -410,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.
@@ -426,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());
@@ -484,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);
@@ -509,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*)));
@@ -625,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,
@@ -641,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;
@@ -657,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());
@@ -683,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";
   }
@@ -703,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.
@@ -740,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();
 
@@ -749,7 +784,7 @@
           CodeInfo code_info = method->GetOptimizedCodeInfo();
           uint32_t native_pc_offset = method->NativeQuickPcOffset(cur_quick_frame_pc_);
           StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
-          if (stack_map.HasInlineInfo(code_info)) {
+          if (stack_map.IsValid() && stack_map.HasInlineInfo(code_info)) {
             InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
             DCHECK_EQ(current_inlining_depth_, 0u);
             for (current_inlining_depth_ = inline_info.GetDepth();
@@ -759,6 +794,7 @@
               if (UNLIKELY(!should_continue)) {
                 return;
               }
+              cur_depth_++;
             }
           }
         }
@@ -786,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()) {
@@ -806,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 {
@@ -841,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 5b43848..79d2f40 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -21,20 +21,20 @@
 #include <string>
 
 #include "arch/instruction_set.h"
+#include "base/bit_utils.h"
 #include "dex_file.h"
 #include "gc_root.h"
 #include "mirror/object_reference.h"
 #include "read_barrier.h"
-#include "utils.h"
 #include "verify_object.h"
 
 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/stack_map.cc b/runtime/stack_map.cc
index 6a0c07d..c36ee05 100644
--- a/runtime/stack_map.cc
+++ b/runtime/stack_map.cc
@@ -18,6 +18,8 @@
 
 #include <stdint.h>
 
+#include "indenter.h"
+
 namespace art {
 
 constexpr size_t DexRegisterLocationCatalog::kNoLocationEntryIndex;
@@ -203,72 +205,95 @@
                                 DexRegisterLocation location,
                                 const std::string& prefix = "v",
                                 const std::string& suffix = "") {
-  os << "      " << prefix << dex_register_num << ": "
-     << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
-     << " (" << location.GetValue() << ")" << suffix << '\n';
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
+  indented_os << prefix << dex_register_num << ": "
+              << DexRegisterLocation::PrettyDescriptor(location.GetInternalKind())
+              << " (" << location.GetValue() << ")" << suffix << '\n';
+}
+
+void CodeInfo::DumpStackMap(std::ostream& os,
+                            size_t stack_map_num,
+                            uint16_t number_of_dex_registers) const {
+  StackMap stack_map = GetStackMapAt(stack_map_num);
+  DumpStackMapHeader(os, stack_map_num);
+  if (stack_map.HasDexRegisterMap(*this)) {
+    DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
+    dex_register_map.Dump(os, *this, number_of_dex_registers);
+  }
 }
 
 void CodeInfo::DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const {
   StackMap stack_map = GetStackMapAt(stack_map_num);
-  os << "    StackMap " << stack_map_num
-     << std::hex
-     << " (dex_pc=0x" << stack_map.GetDexPc(*this)
-     << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
-     << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
-     << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
-     << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
-     << std::dec
-     << ", stack_mask=0b";
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
+  indented_os << "StackMap " << stack_map_num
+              << std::hex
+              << " (dex_pc=0x" << stack_map.GetDexPc(*this)
+              << ", native_pc_offset=0x" << stack_map.GetNativePcOffset(*this)
+              << ", dex_register_map_offset=0x" << stack_map.GetDexRegisterMapOffset(*this)
+              << ", inline_info_offset=0x" << stack_map.GetInlineDescriptorOffset(*this)
+              << ", register_mask=0x" << stack_map.GetRegisterMask(*this)
+              << std::dec
+              << ", stack_mask=0b";
   MemoryRegion stack_mask = stack_map.GetStackMask(*this);
   for (size_t i = 0, e = stack_mask.size_in_bits(); i < e; ++i) {
-    os << stack_mask.LoadBit(e - i - 1);
+    indented_os << stack_mask.LoadBit(e - i - 1);
   }
-  os << ")\n";
+  indented_os << ")\n";
 };
 
-void CodeInfo::Dump(std::ostream& os, uint16_t number_of_dex_registers) const {
+void CodeInfo::Dump(std::ostream& os,
+                    uint16_t number_of_dex_registers,
+                    bool dump_stack_maps) const {
   uint32_t code_info_size = GetOverallSize();
   size_t number_of_stack_maps = GetNumberOfStackMaps();
-  os << "  Optimized CodeInfo (size=" << code_info_size
-     << ", number_of_dex_registers=" << number_of_dex_registers
-     << ", number_of_stack_maps=" << number_of_stack_maps
-     << ", has_inline_info=" << HasInlineInfo()
-     << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
-     << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
-     << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
-     << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
-     << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
-     << ")\n";
-
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
+  indented_os << "Optimized CodeInfo (size=" << code_info_size
+              << ", number_of_dex_registers=" << number_of_dex_registers
+              << ", number_of_stack_maps=" << number_of_stack_maps
+              << ", has_inline_info=" << HasInlineInfo()
+              << ", number_of_bytes_for_inline_info=" << NumberOfBytesForInlineInfo()
+              << ", number_of_bytes_for_dex_register_map=" << NumberOfBytesForDexRegisterMap()
+              << ", number_of_bytes_for_dex_pc=" << NumberOfBytesForDexPc()
+              << ", number_of_bytes_for_native_pc=" << NumberOfBytesForNativePc()
+              << ", number_of_bytes_for_register_mask=" << NumberOfBytesForRegisterMask()
+              << ")\n";
   // Display the Dex register location catalog.
-  size_t number_of_location_catalog_entries = GetNumberOfDexRegisterLocationCatalogEntries();
-  size_t location_catalog_size_in_bytes = GetDexRegisterLocationCatalogSize();
-  os << "  DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
-     << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
-  DexRegisterLocationCatalog dex_register_location_catalog = GetDexRegisterLocationCatalog();
-  for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
-    DexRegisterLocation location = dex_register_location_catalog.GetDexRegisterLocation(i);
-    DumpRegisterMapping(os, i, location, "entry ");
-  }
-
+  GetDexRegisterLocationCatalog().Dump(indented_os, *this);
   // Display stack maps along with (live) Dex register maps.
-  for (size_t i = 0; i < number_of_stack_maps; ++i) {
-    StackMap stack_map = GetStackMapAt(i);
-    DumpStackMapHeader(os, i);
-    if (stack_map.HasDexRegisterMap(*this)) {
-      DexRegisterMap dex_register_map = GetDexRegisterMapOf(stack_map, number_of_dex_registers);
-      dex_register_map.Dump(os, *this, number_of_dex_registers);
+  if (dump_stack_maps) {
+    for (size_t i = 0; i < number_of_stack_maps; ++i) {
+      DumpStackMap(indented_os, i, number_of_dex_registers);
     }
   }
   // TODO: Dump the stack map's inline information? We need to know more from the caller:
   //       we need to know the number of dex registers for each inlined method.
 }
 
+void DexRegisterLocationCatalog::Dump(std::ostream& os, const CodeInfo& code_info) {
+  size_t number_of_location_catalog_entries =
+      code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+  size_t location_catalog_size_in_bytes = code_info.GetDexRegisterLocationCatalogSize();
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
+  indented_os
+      << "DexRegisterLocationCatalog (number_of_entries=" << number_of_location_catalog_entries
+      << ", size_in_bytes=" << location_catalog_size_in_bytes << ")\n";
+  for (size_t i = 0; i < number_of_location_catalog_entries; ++i) {
+    DexRegisterLocation location = GetDexRegisterLocation(i);
+    DumpRegisterMapping(indented_os, i, location, "entry ");
+  }
+}
+
 void DexRegisterMap::Dump(std::ostream& os,
                           const CodeInfo& code_info,
                           uint16_t number_of_dex_registers) const {
   size_t number_of_location_catalog_entries =
       code_info.GetNumberOfDexRegisterLocationCatalogEntries();
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
   // TODO: Display the bit mask of live Dex registers.
   for (size_t j = 0; j < number_of_dex_registers; ++j) {
     if (IsDexRegisterLive(j)) {
@@ -276,7 +301,7 @@
           j, number_of_dex_registers, number_of_location_catalog_entries);
       DexRegisterLocation location = GetDexRegisterLocation(j, number_of_dex_registers, code_info);
       DumpRegisterMapping(
-          os, j, location, "v",
+          indented_os, j, location, "v",
           "\t[entry " + std::to_string(static_cast<int>(location_catalog_entry_index)) + "]");
     }
   }
@@ -285,18 +310,20 @@
 void InlineInfo::Dump(std::ostream& os,
                       const CodeInfo& code_info,
                       uint16_t number_of_dex_registers[]) const {
-  os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
+  Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
+  std::ostream indented_os(&indent_filter);
+  indented_os << "InlineInfo with depth " << static_cast<uint32_t>(GetDepth()) << "\n";
 
   for (size_t i = 0; i < GetDepth(); ++i) {
-    os << " At depth " << i
-       << std::hex
-       << " (dex_pc=0x" << GetDexPcAtDepth(i)
-       << ", method_index=0x" << GetMethodIndexAtDepth(i)
-       << ")\n";
+    indented_os << " At depth " << i
+                << std::hex
+                << " (dex_pc=0x" << GetDexPcAtDepth(i)
+                << ", method_index=0x" << GetMethodIndexAtDepth(i)
+                << ")\n";
     if (HasDexRegisterMapAtDepth(i)) {
       DexRegisterMap dex_register_map =
           code_info.GetDexRegisterMapAtDepth(i, *this, number_of_dex_registers[i]);
-      dex_register_map.Dump(os, code_info, number_of_dex_registers[i]);
+      dex_register_map.Dump(indented_os, code_info, number_of_dex_registers[i]);
     }
   }
 }
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 16ae772..eefdaa7 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -18,8 +18,8 @@
 #define ART_RUNTIME_STACK_MAP_H_
 
 #include "base/bit_vector.h"
+#include "base/bit_utils.h"
 #include "memory_region.h"
-#include "utils.h"
 
 namespace art {
 
@@ -356,6 +356,8 @@
     return region_.size();
   }
 
+  void Dump(std::ostream& os, const CodeInfo& code_info);
+
   // Special (invalid) Dex register location catalog entry index meaning
   // that there is no location for a given Dex register (i.e., it is
   // mapped to a DexRegisterLocation::Kind::kNone location).
@@ -641,6 +643,9 @@
 class StackMap {
  public:
   explicit StackMap(MemoryRegion region) : region_(region) {}
+  StackMap() {}
+
+  bool IsValid() const { return region_.pointer() != nullptr; }
 
   uint32_t GetDexPc(const CodeInfo& info) const;
 
@@ -735,31 +740,43 @@
   }
 
   uint32_t GetMethodIndexAtDepth(uint8_t depth) const {
-    return region_.LoadUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize());
+    return region_.LoadUnaligned<uint32_t>(
+        kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset);
   }
 
   void SetMethodIndexAtDepth(uint8_t depth, uint32_t index) {
-    region_.StoreUnaligned<uint32_t>(kFixedSize + depth * SingleEntrySize(), index);
+    region_.StoreUnaligned<uint32_t>(
+        kFixedSize + depth * SingleEntrySize() + kMethodIndexOffset, index);
   }
 
   uint32_t GetDexPcAtDepth(uint8_t depth) const {
     return region_.LoadUnaligned<uint32_t>(
-        kFixedSize + depth * SingleEntrySize() + sizeof(uint32_t));
+        kFixedSize + depth * SingleEntrySize() + kDexPcOffset);
   }
 
   void SetDexPcAtDepth(uint8_t depth, uint32_t dex_pc) {
     region_.StoreUnaligned<uint32_t>(
-        kFixedSize + depth * SingleEntrySize() + sizeof(uint32_t), dex_pc);
+        kFixedSize + depth * SingleEntrySize() + kDexPcOffset, dex_pc);
+  }
+
+  uint8_t GetInvokeTypeAtDepth(uint8_t depth) const {
+    return region_.LoadUnaligned<uint8_t>(
+        kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset);
+  }
+
+  void SetInvokeTypeAtDepth(uint8_t depth, uint8_t invoke_type) {
+    region_.StoreUnaligned<uint8_t>(
+        kFixedSize + depth * SingleEntrySize() + kInvokeTypeOffset, invoke_type);
   }
 
   uint32_t GetDexRegisterMapOffsetAtDepth(uint8_t depth) const {
     return region_.LoadUnaligned<uint32_t>(
-        kFixedSize + depth * SingleEntrySize() + sizeof(uint32_t) + sizeof(uint32_t));
+        kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset);
   }
 
   void SetDexRegisterMapOffsetAtDepth(uint8_t depth, uint32_t offset) {
     region_.StoreUnaligned<uint32_t>(
-        kFixedSize + depth * SingleEntrySize() + sizeof(uint32_t) + sizeof(uint32_t), offset);
+        kFixedSize + depth * SingleEntrySize() + kDexRegisterMapOffset, offset);
   }
 
   bool HasDexRegisterMapAtDepth(uint8_t depth) const {
@@ -767,7 +784,7 @@
   }
 
   static size_t SingleEntrySize() {
-    return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t);
+    return kFixedEntrySize;
   }
 
   void Dump(std::ostream& os, const CodeInfo& info, uint16_t* number_of_dex_registers) const;
@@ -778,6 +795,12 @@
   static constexpr int kDepthOffset = 0;
   static constexpr int kFixedSize = kDepthOffset + sizeof(uint8_t);
 
+  static constexpr int kMethodIndexOffset = 0;
+  static constexpr int kDexPcOffset = kMethodIndexOffset + sizeof(uint32_t);
+  static constexpr int kInvokeTypeOffset = kDexPcOffset + sizeof(uint32_t);
+  static constexpr int kDexRegisterMapOffset = kInvokeTypeOffset + sizeof(uint8_t);
+  static constexpr int kFixedEntrySize = kDexRegisterMapOffset + sizeof(uint32_t);
+
   MemoryRegion region_;
 
   friend class CodeInfo;
@@ -902,10 +925,6 @@
         + (NumberOfBytesForDexRegisterMap() * sizeof(uint8_t));
   }
 
-  uint32_t GetDexRegisterLocationCatalogOffset() const {
-    return kFixedSize;
-  }
-
   DexRegisterLocationCatalog GetDexRegisterLocationCatalog() const {
     return DexRegisterLocationCatalog(region_.Subregion(
         GetDexRegisterLocationCatalogOffset(),
@@ -970,14 +989,18 @@
     return StackMapSize() * GetNumberOfStackMaps();
   }
 
-  size_t GetDexRegisterMapsOffset() const {
+  uint32_t GetDexRegisterLocationCatalogOffset() const {
     return GetStackMapsOffset() + GetStackMapsSize();
   }
 
-  uint32_t GetStackMapsOffset() const {
+  size_t GetDexRegisterMapsOffset() const {
     return GetDexRegisterLocationCatalogOffset() + GetDexRegisterLocationCatalogSize();
   }
 
+  uint32_t GetStackMapsOffset() const {
+    return kFixedSize;
+  }
+
   DexRegisterMap GetDexRegisterMapOf(StackMap stack_map, uint32_t number_of_dex_registers) const {
     DCHECK(stack_map.HasDexRegisterMap(*this));
     uint32_t offset = GetDexRegisterMapsOffset() + stack_map.GetDexRegisterMapOffset(*this);
@@ -1011,8 +1034,7 @@
         return stack_map;
       }
     }
-    LOG(FATAL) << "Unreachable";
-    UNREACHABLE();
+    return StackMap();
   }
 
   StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const {
@@ -1023,11 +1045,18 @@
         return stack_map;
       }
     }
-    LOG(FATAL) << "Unreachable";
-    UNREACHABLE();
+    return StackMap();
   }
 
-  void Dump(std::ostream& os, uint16_t number_of_dex_registers) const;
+  // Dump this CodeInfo object on `os`.  If `dump_stack_maps` is true,
+  // also dump the stack maps and the associated Dex register maps.
+  void Dump(std::ostream& os, uint16_t number_of_dex_registers, bool dump_stack_maps) const;
+
+  // Dump stack map number `stack_map_num` as well as associated data on `os`,
+  // such as Dex register locations.
+  void DumpStackMap(std::ostream& os, size_t stack_map_num, uint16_t number_of_dex_registers) const;
+  // Dump the header of stack map number `stack_map_num` on `os`, without
+  // associated data.
   void DumpStackMapHeader(std::ostream& os, size_t stack_map_num) const;
 
  private:
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 2145c9c..65999f7 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -33,6 +33,8 @@
 
 #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"
 #include "base/to_str.h"
@@ -49,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"
@@ -755,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.
@@ -957,7 +958,7 @@
   }
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    mirror::ArtMethod* m = GetMethod();
+    ArtMethod* m = GetMethod();
     if (m->IsRuntimeMethod()) {
       return true;
     }
@@ -1028,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;
@@ -1059,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();
 }
 
@@ -1540,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;
@@ -1577,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) {
+    // Allocate method trace with format [method pointers][pcs].
+    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:
@@ -1642,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>
@@ -1664,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;
@@ -1687,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;
 
@@ -1703,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;
     }
@@ -1715,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));
@@ -1728,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)));
@@ -1789,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;
@@ -1804,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);
@@ -1851,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);
@@ -2128,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;
@@ -2141,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) {
@@ -2188,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()) {
@@ -2232,28 +2227,26 @@
 
  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);
         CodeInfo code_info = m->GetOptimizedCodeInfo();
         StackMap map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+        DCHECK(map.IsValid());
         MemoryRegion mask = map.GetStackMask(code_info);
         // 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;
@@ -2289,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
@@ -2360,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);
@@ -2391,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 9346813..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;
@@ -61,6 +60,7 @@
   template<class T> class PrimitiveArray;
   typedef PrimitiveArray<int32_t> IntArray;
   class StackTraceElement;
+  class String;
   class Throwable;
 }  // namespace mirror
 
@@ -68,6 +68,7 @@
 class MethodVerifier;
 }  // namespace verifier
 
+class ArtMethod;
 class BaseMutex;
 class ClassLinker;
 class Closure;
@@ -373,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
@@ -381,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);
   }
 
@@ -809,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;
   }
 
@@ -1160,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/thread_linux.cc b/runtime/thread_linux.cc
index 0526f49..0731f30 100644
--- a/runtime/thread_linux.cc
+++ b/runtime/thread_linux.cc
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#include "thread.h"
-
 #include <signal.h>
 
+#include "thread.h"
+#include "utils.h"
+
 namespace art {
 
 void Thread::SetNativePriority(int) {
diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc
index cc54bbd..7719bb8 100644
--- a/runtime/thread_list.cc
+++ b/runtime/thread_list.cc
@@ -30,6 +30,7 @@
 #include "base/histogram-inl.h"
 #include "base/mutex.h"
 #include "base/mutex-inl.h"
+#include "base/time_utils.h"
 #include "base/timing_logger.h"
 #include "debugger.h"
 #include "jni_internal.h"
@@ -38,7 +39,6 @@
 #include "scoped_thread_state_change.h"
 #include "thread.h"
 #include "trace.h"
-#include "utils.h"
 #include "well_known_classes.h"
 
 namespace art {
diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc
index ce76eae..1e84c9d 100644
--- a/runtime/thread_pool.cc
+++ b/runtime/thread_pool.cc
@@ -18,6 +18,7 @@
 
 #include "base/casts.h"
 #include "base/stl_util.h"
+#include "base/time_utils.h"
 #include "runtime.h"
 #include "thread-inl.h"
 
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 7636792..d3b3af8 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -22,15 +22,16 @@
 #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"
 #include "base/unix_file/fd_file.h"
 #include "class_linker.h"
 #include "common_throws.h"
 #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"
@@ -40,6 +41,7 @@
 #include "ScopedLocalRef.h"
 #include "thread.h"
 #include "thread_list.h"
+#include "utils.h"
 #include "entrypoints/quick/quick_entrypoints.h"
 
 namespace art {
@@ -96,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);
@@ -105,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             = '*';
@@ -118,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);
 }
@@ -246,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.
@@ -271,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);
@@ -279,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);
@@ -638,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);
@@ -654,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*)));
       }
     }
   }
@@ -668,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);
@@ -759,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.
@@ -774,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);
@@ -783,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);
@@ -792,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;
@@ -802,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);
@@ -816,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);
@@ -838,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()));
@@ -867,8 +877,9 @@
   return false;
 }
 
-static std::string GetMethodLine(mirror::ArtMethod* method)
+static std::string GetMethodLine(ArtMethod* method)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  method = method->GetInterfaceMethodIfProxy(sizeof(void*));
   return StringPrintf("%p\t%s\t%s\t%s\t%s\n", method,
       PrettyDescriptor(method->GetDeclaringClassDescriptor()).c_str(), method->GetName(),
       method->GetSignature().ToString().c_str(), method->GetDeclaringClassSourceFile());
@@ -900,7 +911,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.
@@ -934,11 +945,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;
@@ -947,8 +958,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);
@@ -957,7 +968,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.
@@ -988,19 +999,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 7986cdc..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"
@@ -42,7 +42,6 @@
 #if defined(__APPLE__)
 #include "AvailabilityMacros.h"  // For MAC_OS_X_VERSION_MAX_ALLOWED
 #include <sys/syscall.h>
-#include <sys/time.h>
 #endif
 
 #include <backtrace/Backtrace.h>  // For DumpNativeStack.
@@ -204,102 +203,6 @@
   }
 }
 
-std::string GetIsoDate() {
-  time_t now = time(nullptr);
-  tm tmbuf;
-  tm* ptm = localtime_r(&now, &tmbuf);
-  return StringPrintf("%04d-%02d-%02d %02d:%02d:%02d",
-      ptm->tm_year + 1900, ptm->tm_mon+1, ptm->tm_mday,
-      ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
-}
-
-uint64_t MilliTime() {
-#if defined(__linux__)
-  timespec now;
-  clock_gettime(CLOCK_MONOTONIC, &now);
-  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_nsec / UINT64_C(1000000);
-#else  // __APPLE__
-  timeval now;
-  gettimeofday(&now, nullptr);
-  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_usec / UINT64_C(1000);
-#endif
-}
-
-uint64_t MicroTime() {
-#if defined(__linux__)
-  timespec now;
-  clock_gettime(CLOCK_MONOTONIC, &now);
-  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_nsec / UINT64_C(1000);
-#else  // __APPLE__
-  timeval now;
-  gettimeofday(&now, nullptr);
-  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000) + now.tv_usec;
-#endif
-}
-
-uint64_t NanoTime() {
-#if defined(__linux__)
-  timespec now;
-  clock_gettime(CLOCK_MONOTONIC, &now);
-  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec;
-#else  // __APPLE__
-  timeval now;
-  gettimeofday(&now, nullptr);
-  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_usec * UINT64_C(1000);
-#endif
-}
-
-uint64_t ThreadCpuNanoTime() {
-#if defined(__linux__)
-  timespec now;
-  clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
-  return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000000000) + now.tv_nsec;
-#else  // __APPLE__
-  UNIMPLEMENTED(WARNING);
-  return -1;
-#endif
-}
-
-void NanoSleep(uint64_t ns) {
-  timespec tm;
-  tm.tv_sec = ns / MsToNs(1000);
-  tm.tv_nsec = ns - static_cast<uint64_t>(tm.tv_sec) * MsToNs(1000);
-  nanosleep(&tm, nullptr);
-}
-
-void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts) {
-  int64_t endSec;
-
-  if (absolute) {
-#if !defined(__APPLE__)
-    clock_gettime(clock, ts);
-#else
-    UNUSED(clock);
-    timeval tv;
-    gettimeofday(&tv, nullptr);
-    ts->tv_sec = tv.tv_sec;
-    ts->tv_nsec = tv.tv_usec * 1000;
-#endif
-  } else {
-    ts->tv_sec = 0;
-    ts->tv_nsec = 0;
-  }
-  endSec = ts->tv_sec + ms / 1000;
-  if (UNLIKELY(endSec >= 0x7fffffff)) {
-    std::ostringstream ss;
-    LOG(INFO) << "Note: end time exceeds epoch: " << ss.str();
-    endSec = 0x7ffffffe;
-  }
-  ts->tv_sec = endSec;
-  ts->tv_nsec = (ts->tv_nsec + (ms % 1000) * 1000000) + ns;
-
-  // Catch rollover.
-  if (ts->tv_nsec >= 1000000000L) {
-    ts->tv_sec++;
-    ts->tv_nsec -= 1000000000L;
-  }
-}
-
 std::string PrettyDescriptor(mirror::String* java_descriptor) {
   if (java_descriptor == nullptr) {
     return "null";
@@ -441,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();
@@ -578,88 +484,6 @@
                       negative_str, byte_count / kBytesPerUnit[i], kUnitStrings[i]);
 }
 
-std::string PrettyDuration(uint64_t nano_duration, size_t max_fraction_digits) {
-  if (nano_duration == 0) {
-    return "0";
-  } else {
-    return FormatDuration(nano_duration, GetAppropriateTimeUnit(nano_duration),
-                          max_fraction_digits);
-  }
-}
-
-TimeUnit GetAppropriateTimeUnit(uint64_t nano_duration) {
-  const uint64_t one_sec = 1000 * 1000 * 1000;
-  const uint64_t one_ms  = 1000 * 1000;
-  const uint64_t one_us  = 1000;
-  if (nano_duration >= one_sec) {
-    return kTimeUnitSecond;
-  } else if (nano_duration >= one_ms) {
-    return kTimeUnitMillisecond;
-  } else if (nano_duration >= one_us) {
-    return kTimeUnitMicrosecond;
-  } else {
-    return kTimeUnitNanosecond;
-  }
-}
-
-uint64_t GetNsToTimeUnitDivisor(TimeUnit time_unit) {
-  const uint64_t one_sec = 1000 * 1000 * 1000;
-  const uint64_t one_ms  = 1000 * 1000;
-  const uint64_t one_us  = 1000;
-
-  switch (time_unit) {
-    case kTimeUnitSecond:
-      return one_sec;
-    case kTimeUnitMillisecond:
-      return one_ms;
-    case kTimeUnitMicrosecond:
-      return one_us;
-    case kTimeUnitNanosecond:
-      return 1;
-  }
-  return 0;
-}
-
-std::string FormatDuration(uint64_t nano_duration, TimeUnit time_unit,
-                           size_t max_fraction_digits) {
-  const char* unit = nullptr;
-  uint64_t divisor = GetNsToTimeUnitDivisor(time_unit);
-  switch (time_unit) {
-    case kTimeUnitSecond:
-      unit = "s";
-      break;
-    case kTimeUnitMillisecond:
-      unit = "ms";
-      break;
-    case kTimeUnitMicrosecond:
-      unit = "us";
-      break;
-    case kTimeUnitNanosecond:
-      unit = "ns";
-      break;
-  }
-  const uint64_t whole_part = nano_duration / divisor;
-  uint64_t fractional_part = nano_duration % divisor;
-  if (fractional_part == 0) {
-    return StringPrintf("%" PRIu64 "%s", whole_part, unit);
-  } else {
-    static constexpr size_t kMaxDigits = 30;
-    size_t avail_digits = kMaxDigits;
-    char fraction_buffer[kMaxDigits];
-    char* ptr = fraction_buffer;
-    uint64_t multiplier = 10;
-    // This infinite loops if fractional part is 0.
-    while (avail_digits > 1 && fractional_part * multiplier < divisor) {
-      multiplier *= 10;
-      *ptr++ = '0';
-      avail_digits--;
-    }
-    snprintf(ptr, avail_digits, "%" PRIu64, fractional_part);
-    fraction_buffer[std::min(kMaxDigits - 1, max_fraction_digits)] = '\0';
-    return StringPrintf("%" PRIu64 ".%s%s", whole_part, fraction_buffer, unit);
-  }
-}
-
 std::string PrintableChar(uint16_t ch) {
   std::string result;
   result += '\'';
@@ -774,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;
@@ -792,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 += "__";
@@ -1267,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 71ccf85..1ef98e7 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -34,22 +34,15 @@
 namespace art {
 
 class ArtField;
+class ArtMethod;
 class DexFile;
 
 namespace mirror {
-class ArtMethod;
 class Class;
 class Object;
 class String;
 }  // namespace mirror
 
-enum TimeUnit {
-  kTimeUnitNanosecond,
-  kTimeUnitMicrosecond,
-  kTimeUnitMillisecond,
-  kTimeUnitSecond,
-};
-
 template <typename T>
 bool ParseUint(const char *in, T* out) {
   char* end;
@@ -78,228 +71,6 @@
   return true;
 }
 
-template<typename T>
-static constexpr bool IsPowerOfTwo(T x) {
-  return (x & (x - 1)) == 0;
-}
-
-template<int n, typename T>
-static inline bool IsAligned(T x) {
-  static_assert((n & (n - 1)) == 0, "n is not a power of two");
-  return (x & (n - 1)) == 0;
-}
-
-template<int n, typename T>
-static inline bool IsAligned(T* x) {
-  return IsAligned<n>(reinterpret_cast<const uintptr_t>(x));
-}
-
-template<typename T>
-static inline bool IsAlignedParam(T x, int n) {
-  return (x & (n - 1)) == 0;
-}
-
-#define CHECK_ALIGNED(value, alignment) \
-  CHECK(::art::IsAligned<alignment>(value)) << reinterpret_cast<const void*>(value)
-
-#define DCHECK_ALIGNED(value, alignment) \
-  DCHECK(::art::IsAligned<alignment>(value)) << reinterpret_cast<const void*>(value)
-
-#define DCHECK_ALIGNED_PARAM(value, alignment) \
-  DCHECK(::art::IsAlignedParam(value, alignment)) << reinterpret_cast<const void*>(value)
-
-// Check whether an N-bit two's-complement representation can hold value.
-template <typename T>
-static inline bool IsInt(int N, T value) {
-  int bitsPerT = sizeof(T) * kBitsPerByte;
-  if (N == bitsPerT) {
-    return true;
-  } else {
-    CHECK_LT(0, N);
-    CHECK_LT(N, bitsPerT);
-    T limit = static_cast<T>(1) << (N - 1);
-    return (-limit <= value) && (value < limit);
-  }
-}
-
-template <typename T>
-static constexpr T GetIntLimit(size_t bits) {
-  return
-      DCHECK_CONSTEXPR(bits > 0, "bits cannot be zero", 0)
-      DCHECK_CONSTEXPR(bits < kBitsPerByte * sizeof(T), "kBits must be < max.", 0)
-      static_cast<T>(1) << (bits - 1);
-}
-
-template <size_t kBits, typename T>
-static constexpr bool IsInt(T value) {
-  static_assert(kBits > 0, "kBits cannot be zero.");
-  static_assert(kBits <= kBitsPerByte * sizeof(T), "kBits must be <= max.");
-  static_assert(std::is_signed<T>::value, "Needs a signed type.");
-  // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
-  // trivially true.
-  return (kBits == kBitsPerByte * sizeof(T)) ?
-      true :
-      (-GetIntLimit<T>(kBits) <= value) && (value < GetIntLimit<T>(kBits));
-}
-
-template <size_t kBits, typename T>
-static constexpr bool IsUint(T value) {
-  static_assert(kBits > 0, "kBits cannot be zero.");
-  static_assert(kBits <= kBitsPerByte * sizeof(T), "kBits must be <= max.");
-  static_assert(std::is_integral<T>::value, "Needs an integral type.");
-  // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
-  // trivially true.
-  return (0 <= value) &&
-      (kBits == kBitsPerByte * sizeof(T) ||
-          (static_cast<typename std::make_unsigned<T>::type>(value) <=
-               GetIntLimit<typename std::make_unsigned<T>::type>(kBits + 1) - 1));
-}
-
-template <size_t kBits, typename T>
-static constexpr bool IsAbsoluteUint(T value) {
-  static_assert(kBits <= kBitsPerByte * sizeof(T), "kBits must be < max.");
-  return (kBits == kBitsPerByte * sizeof(T)) ?
-      true :
-      IsUint<kBits, T>(value < 0 ? -value : value);
-}
-
-static inline uint16_t Low16Bits(uint32_t value) {
-  return static_cast<uint16_t>(value);
-}
-
-static inline uint16_t High16Bits(uint32_t value) {
-  return static_cast<uint16_t>(value >> 16);
-}
-
-static inline uint32_t Low32Bits(uint64_t value) {
-  return static_cast<uint32_t>(value);
-}
-
-static inline uint32_t High32Bits(uint64_t value) {
-  return static_cast<uint32_t>(value >> 32);
-}
-
-// Traits class providing an unsigned integer type of (byte) size `n`.
-template <size_t n>
-struct UnsignedIntegerType {
-  // No defined `type`.
-};
-
-template <>
-struct UnsignedIntegerType<1> { typedef uint8_t type; };
-
-template <>
-struct UnsignedIntegerType<2> { typedef uint16_t type; };
-
-template <>
-struct UnsignedIntegerType<4> { typedef uint32_t type; };
-
-template <>
-struct UnsignedIntegerType<8> { typedef uint64_t type; };
-
-// Type identity.
-template <typename T>
-struct TypeIdentity {
-  typedef T type;
-};
-
-// Like sizeof, but count how many bits a type takes. Pass type explicitly.
-template <typename T>
-static constexpr size_t BitSizeOf() {
-  return sizeof(T) * CHAR_BIT;
-}
-
-// Like sizeof, but count how many bits a type takes. Infers type from parameter.
-template <typename T>
-static constexpr size_t BitSizeOf(T /*x*/) {
-  return sizeof(T) * CHAR_BIT;
-}
-
-// For rounding integers.
-template<typename T>
-static constexpr T RoundDown(T x, typename TypeIdentity<T>::type n) WARN_UNUSED;
-
-template<typename T>
-static constexpr T RoundDown(T x, typename TypeIdentity<T>::type n) {
-  return
-      DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))
-      (x & -n);
-}
-
-template<typename T>
-static constexpr T RoundUp(T x, typename TypeIdentity<T>::type n) WARN_UNUSED;
-
-template<typename T>
-static constexpr T RoundUp(T x, typename TypeIdentity<T>::type n) {
-  return RoundDown(x + n - 1, n);
-}
-
-// For aligning pointers.
-template<typename T>
-static inline T* AlignDown(T* x, uintptr_t n) WARN_UNUSED;
-
-template<typename T>
-static inline T* AlignDown(T* x, uintptr_t n) {
-  return reinterpret_cast<T*>(RoundDown(reinterpret_cast<uintptr_t>(x), n));
-}
-
-template<typename T>
-static inline T* AlignUp(T* x, uintptr_t n) WARN_UNUSED;
-
-template<typename T>
-static inline T* AlignUp(T* x, uintptr_t n) {
-  return reinterpret_cast<T*>(RoundUp(reinterpret_cast<uintptr_t>(x), n));
-}
-
-namespace utils {
-namespace detail {  // Private, implementation-specific namespace. Do not poke outside of this file.
-template <typename T>
-static constexpr inline T RoundUpToPowerOfTwoRecursive(T x, size_t bit) {
-  return bit == (BitSizeOf<T>()) ? x: RoundUpToPowerOfTwoRecursive(x | x >> bit, bit << 1);
-}
-}  // namespace detail
-}  // namespace utils
-
-// Recursive implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
-// figure 3-3, page 48, where the function is called clp2.
-template <typename T>
-static constexpr inline T RoundUpToPowerOfTwo(T x) {
-  return art::utils::detail::RoundUpToPowerOfTwoRecursive(x - 1, 1) + 1;
-}
-
-// Find the bit position of the most significant bit (0-based), or -1 if there were no bits set.
-template <typename T>
-static constexpr ssize_t MostSignificantBit(T value) {
-  return (value == 0) ? -1 : (MostSignificantBit(value >> 1) + 1);
-}
-
-// How many bits (minimally) does it take to store the constant 'value'? i.e. 1 for 1, 3 for 5, etc.
-template <typename T>
-static constexpr size_t MinimumBitsToStore(T value) {
-  return static_cast<size_t>(MostSignificantBit(value) + 1);
-}
-
-template<typename T>
-static constexpr int CLZ(T x) {
-  static_assert(sizeof(T) <= sizeof(long long), "T too large, must be smaller than long long");  // NOLINT [runtime/int] [4]
-  return (sizeof(T) == sizeof(uint32_t))
-      ? __builtin_clz(x)  // TODO: __builtin_clz[ll] has undefined behavior for x=0
-      : __builtin_clzll(x);
-}
-
-template<typename T>
-static constexpr int CTZ(T x) {
-  return (sizeof(T) == sizeof(uint32_t))
-      ? __builtin_ctz(x)
-      : __builtin_ctzll(x);
-}
-
-template<typename T>
-static inline int WhichPowerOf2(T x) {
-  DCHECK((x != 0) && IsPowerOfTwo(x));
-  return CTZ(x);
-}
-
 // Return whether x / divisor == x * (1.0f / divisor), for every float x.
 static constexpr bool CanDivideByReciprocalMultiplyFloat(int32_t divisor) {
   // True, if the most significant bits of divisor are 0.
@@ -312,13 +83,6 @@
   return ((divisor & ((UINT64_C(1) << 52) - 1)) == 0);
 }
 
-template<typename T>
-static constexpr int POPCOUNT(T x) {
-  return (sizeof(T) == sizeof(uint32_t))
-      ? __builtin_popcount(x)
-      : __builtin_popcountll(x);
-}
-
 static inline uint32_t PointerToLowMemUInt32(const void* p) {
   uintptr_t intp = reinterpret_cast<uintptr_t>(p);
   DCHECK_LE(intp, 0xFFFFFFFFU);
@@ -361,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);
 
@@ -392,21 +156,6 @@
 // Returns a human-readable size string such as "1MB".
 std::string PrettySize(int64_t size_in_bytes);
 
-// Returns a human-readable time string which prints every nanosecond while trying to limit the
-// number of trailing zeros. Prints using the largest human readable unit up to a second.
-// e.g. "1ms", "1.000000001s", "1.001us"
-std::string PrettyDuration(uint64_t nano_duration, size_t max_fraction_digits = 3);
-
-// Format a nanosecond time to specified units.
-std::string FormatDuration(uint64_t nano_duration, TimeUnit time_unit,
-                           size_t max_fraction_digits);
-
-// Get the appropriate unit for a nanosecond duration.
-TimeUnit GetAppropriateTimeUnit(uint64_t nano_duration);
-
-// Get the divisor to convert from a nanoseconds to a time unit.
-uint64_t GetNsToTimeUnitDivisor(TimeUnit time_unit);
-
 // Performs JNI name mangling as described in section 11.3 "Linking Native Methods"
 // of the JNI spec.
 std::string MangleForJni(const std::string& s);
@@ -432,52 +181,15 @@
 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);
 bool PrintFileToLog(const std::string& file_name, LogSeverity level);
 
-// Returns the current date in ISO yyyy-mm-dd hh:mm:ss format.
-std::string GetIsoDate();
-
-// Returns the monotonic time since some unspecified starting point in milliseconds.
-uint64_t MilliTime();
-
-// Returns the monotonic time since some unspecified starting point in microseconds.
-uint64_t MicroTime();
-
-// Returns the monotonic time since some unspecified starting point in nanoseconds.
-uint64_t NanoTime();
-
-// Returns the thread-specific CPU-time clock in nanoseconds or -1 if unavailable.
-uint64_t ThreadCpuNanoTime();
-
-// Converts the given number of nanoseconds to milliseconds.
-static constexpr inline uint64_t NsToMs(uint64_t ns) {
-  return ns / 1000 / 1000;
-}
-
-// Converts the given number of milliseconds to nanoseconds
-static constexpr inline uint64_t MsToNs(uint64_t ns) {
-  return ns * 1000 * 1000;
-}
-
-#if defined(__APPLE__)
-// No clocks to specify on OS/X, fake value to pass to routines that require a clock.
-#define CLOCK_REALTIME 0xebadf00d
-#endif
-
-// Sleep for the given number of nanoseconds, a bad way to handle contention.
-void NanoSleep(uint64_t ns);
-
-// Initialize a timespec to either a relative time (ms,ns), or to the absolute
-// time corresponding to the indicated clock value plus the supplied offset.
-void InitTimeSpec(bool absolute, int clock, int64_t ms, int32_t ns, timespec* ts);
-
 // Splits a string using the given separator character into a vector of
 // strings. Empty strings will be omitted.
 void Split(const std::string& s, char separator, std::vector<std::string>* result);
@@ -509,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.
@@ -608,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 869d305..66e38b1 100644
--- a/runtime/utils_test.cc
+++ b/runtime/utils_test.cc
@@ -172,35 +172,6 @@
   EXPECT_EQ("512B", PrettySize(512));
 }
 
-TEST_F(UtilsTest, PrettyDuration) {
-  const uint64_t one_sec = 1000000000;
-  const uint64_t one_ms  = 1000000;
-  const uint64_t one_us  = 1000;
-
-  EXPECT_EQ("1s", PrettyDuration(1 * one_sec));
-  EXPECT_EQ("10s", PrettyDuration(10 * one_sec));
-  EXPECT_EQ("100s", PrettyDuration(100 * one_sec));
-  EXPECT_EQ("1.001s", PrettyDuration(1 * one_sec + one_ms));
-  EXPECT_EQ("1.000001s", PrettyDuration(1 * one_sec + one_us, 6));
-  EXPECT_EQ("1.000000001s", PrettyDuration(1 * one_sec + 1, 9));
-  EXPECT_EQ("1.000s", PrettyDuration(1 * one_sec + one_us, 3));
-
-  EXPECT_EQ("1ms", PrettyDuration(1 * one_ms));
-  EXPECT_EQ("10ms", PrettyDuration(10 * one_ms));
-  EXPECT_EQ("100ms", PrettyDuration(100 * one_ms));
-  EXPECT_EQ("1.001ms", PrettyDuration(1 * one_ms + one_us));
-  EXPECT_EQ("1.000001ms", PrettyDuration(1 * one_ms + 1, 6));
-
-  EXPECT_EQ("1us", PrettyDuration(1 * one_us));
-  EXPECT_EQ("10us", PrettyDuration(10 * one_us));
-  EXPECT_EQ("100us", PrettyDuration(100 * one_us));
-  EXPECT_EQ("1.001us", PrettyDuration(1 * one_us + 1));
-
-  EXPECT_EQ("1ns", PrettyDuration(1));
-  EXPECT_EQ("10ns", PrettyDuration(10));
-  EXPECT_EQ("100ns", PrettyDuration(100));
-}
-
 TEST_F(UtilsTest, MangleForJni) {
   ScopedObjectAccess soa(Thread::Current());
   EXPECT_EQ("hello_00024world", MangleForJni("hello$world"));
@@ -214,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));
@@ -408,119 +379,6 @@
   }
 }
 
-TEST_F(UtilsTest, RoundUpToPowerOfTwo) {
-  // Tests the constexpr variant since all the parameters are constexpr
-  EXPECT_EQ(0, RoundUpToPowerOfTwo(0));
-  EXPECT_EQ(1, RoundUpToPowerOfTwo(1));
-  EXPECT_EQ(2, RoundUpToPowerOfTwo(2));
-  EXPECT_EQ(4, RoundUpToPowerOfTwo(3));
-  EXPECT_EQ(8, RoundUpToPowerOfTwo(7));
-
-  EXPECT_EQ(0b10000L, RoundUpToPowerOfTwo(0b01101L));
-  EXPECT_EQ(1ULL << 63, RoundUpToPowerOfTwo(1ULL << 62 | 1ULL));
-}
-
-TEST_F(UtilsTest, MostSignificantBit) {
-  EXPECT_EQ(-1, MostSignificantBit(0));
-  EXPECT_EQ(0, MostSignificantBit(1));
-  EXPECT_EQ(31, MostSignificantBit(~static_cast<uint32_t>(0)));
-  EXPECT_EQ(2, MostSignificantBit(0b110));
-  EXPECT_EQ(2, MostSignificantBit(0b100));
-}
-
-TEST_F(UtilsTest, MinimumBitsToStore) {
-  EXPECT_EQ(0u, MinimumBitsToStore(0));
-  EXPECT_EQ(1u, MinimumBitsToStore(1));
-  EXPECT_EQ(2u, MinimumBitsToStore(0b10));
-  EXPECT_EQ(2u, MinimumBitsToStore(0b11));
-  EXPECT_EQ(3u, MinimumBitsToStore(0b100));
-  EXPECT_EQ(3u, MinimumBitsToStore(0b110));
-  EXPECT_EQ(3u, MinimumBitsToStore(0b101));
-  EXPECT_EQ(8u, MinimumBitsToStore(0xFF));
-  EXPECT_EQ(32u, MinimumBitsToStore(~static_cast<uint32_t>(0)));
-}
-
-static constexpr int64_t INT_MIN_minus1 = static_cast<int64_t>(INT_MIN) - 1;
-static constexpr int64_t INT_MAX_plus1 = static_cast<int64_t>(INT_MAX) + 1;
-static constexpr int64_t UINT_MAX_plus1 = static_cast<int64_t>(UINT_MAX) + 1;
-
-TEST_F(UtilsTest, IsInt) {
-  EXPECT_FALSE(IsInt(1, -2));
-  EXPECT_TRUE(IsInt(1, -1));
-  EXPECT_TRUE(IsInt(1, 0));
-  EXPECT_FALSE(IsInt(1, 1));
-
-  EXPECT_FALSE(IsInt(4, -9));
-  EXPECT_TRUE(IsInt(4, -8));
-  EXPECT_TRUE(IsInt(4, 7));
-  EXPECT_FALSE(IsInt(4, 8));
-
-  EXPECT_FALSE(IsInt(32, INT_MIN_minus1));
-  EXPECT_TRUE(IsInt(32, INT_MIN));
-  EXPECT_TRUE(IsInt(32, INT_MAX));
-  EXPECT_FALSE(IsInt(32, INT_MAX_plus1));
-}
-
-TEST_F(UtilsTest, IsInt_Static) {
-  EXPECT_FALSE(IsInt<1>(-2));
-  EXPECT_TRUE(IsInt<1>(-1));
-  EXPECT_TRUE(IsInt<1>(0));
-  EXPECT_FALSE(IsInt<1>(1));
-
-  EXPECT_FALSE(IsInt<4>(-9));
-  EXPECT_TRUE(IsInt<4>(-8));
-  EXPECT_TRUE(IsInt<4>(7));
-  EXPECT_FALSE(IsInt<4>(8));
-
-  EXPECT_FALSE(IsInt<32>(INT_MIN_minus1));
-  EXPECT_TRUE(IsInt<32>(INT_MIN));
-  EXPECT_TRUE(IsInt<32>(INT_MAX));
-  EXPECT_FALSE(IsInt<32>(INT_MAX_plus1));
-}
-
-TEST_F(UtilsTest, IsUint) {
-  EXPECT_FALSE(IsUint<1>(-1));
-  EXPECT_TRUE(IsUint<1>(0));
-  EXPECT_TRUE(IsUint<1>(1));
-  EXPECT_FALSE(IsUint<1>(2));
-
-  EXPECT_FALSE(IsUint<4>(-1));
-  EXPECT_TRUE(IsUint<4>(0));
-  EXPECT_TRUE(IsUint<4>(15));
-  EXPECT_FALSE(IsUint<4>(16));
-
-  EXPECT_FALSE(IsUint<32>(-1));
-  EXPECT_TRUE(IsUint<32>(0));
-  EXPECT_TRUE(IsUint<32>(UINT_MAX));
-  EXPECT_FALSE(IsUint<32>(UINT_MAX_plus1));
-}
-
-TEST_F(UtilsTest, IsAbsoluteUint) {
-  EXPECT_FALSE(IsAbsoluteUint<1>(-2));
-  EXPECT_TRUE(IsAbsoluteUint<1>(-1));
-  EXPECT_TRUE(IsAbsoluteUint<32>(0));
-  EXPECT_TRUE(IsAbsoluteUint<1>(1));
-  EXPECT_FALSE(IsAbsoluteUint<1>(2));
-
-  EXPECT_FALSE(IsAbsoluteUint<4>(-16));
-  EXPECT_TRUE(IsAbsoluteUint<4>(-15));
-  EXPECT_TRUE(IsAbsoluteUint<32>(0));
-  EXPECT_TRUE(IsAbsoluteUint<4>(15));
-  EXPECT_FALSE(IsAbsoluteUint<4>(16));
-
-  EXPECT_FALSE(IsAbsoluteUint<32>(-UINT_MAX_plus1));
-  EXPECT_TRUE(IsAbsoluteUint<32>(-UINT_MAX));
-  EXPECT_TRUE(IsAbsoluteUint<32>(0));
-  EXPECT_TRUE(IsAbsoluteUint<32>(UINT_MAX));
-  EXPECT_FALSE(IsAbsoluteUint<32>(UINT_MAX_plus1));
-}
-
-TEST_F(UtilsTest, TestSleep) {
-  auto start = NanoTime();
-  NanoSleep(MsToNs(1500));
-  EXPECT_GT(NanoTime() - start, MsToNs(1000));
-}
-
 TEST_F(UtilsTest, IsValidDescriptor) {
   std::vector<uint8_t> descriptor(
       { 'L', 'a', '/', 'b', '$', 0xed, 0xa0, 0x80, 0xed, 0xb0, 0x80, ';', 0x00 });
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 1b1bc54..f25e4ee 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -19,8 +19,10 @@
 #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"
 #include "class_linker.h"
 #include "compiler_callbacks.h"
 #include "dex_file-inl.h"
@@ -31,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"
@@ -41,6 +42,7 @@
 #include "register_line-inl.h"
 #include "runtime.h"
 #include "scoped_thread_state_change.h"
+#include "utils.h"
 #include "handle_scope-inl.h"
 #include "verifier/dex_gc_map.h"
 
@@ -113,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);
 }
 
@@ -160,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,
@@ -195,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,
@@ -212,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;
@@ -243,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,
@@ -260,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;
@@ -287,6 +280,10 @@
 }
 
 static bool IsLargeMethod(const DexFile::CodeItem* const code_item) {
+  if (code_item == nullptr) {
+    return false;
+  }
+
   uint16_t registers_size = code_item->registers_size_;
   uint32_t insns_size = code_item->insns_size_in_code_units_;
 
@@ -299,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) {
@@ -349,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,
@@ -373,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)
@@ -412,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;
@@ -459,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);
 }
 
@@ -491,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
@@ -524,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();
 }
@@ -2368,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 {
@@ -2402,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;
@@ -2417,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,
@@ -2484,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();
@@ -2509,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()) {
@@ -2837,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);
@@ -3188,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()) {
@@ -3203,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 "
@@ -3281,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).
@@ -3414,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()) {
   }
@@ -3432,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_) {
@@ -3483,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 {
@@ -3515,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_);
@@ -3530,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;
@@ -4241,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(),
@@ -4268,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/sigchainlib/sigchain.cc b/sigchainlib/sigchain.cc
index 0359ed3..1391d14 100644
--- a/sigchainlib/sigchain.cc
+++ b/sigchainlib/sigchain.cc
@@ -39,7 +39,7 @@
 
 class SignalAction {
  public:
-  SignalAction() : claimed_(false), uses_old_style_(false) {
+  SignalAction() : claimed_(false), uses_old_style_(false), special_handler_(nullptr) {
   }
 
   // Claim the signal and keep the action specified.
@@ -77,10 +77,19 @@
     return uses_old_style_;
   }
 
+  void SetSpecialHandler(SpecialSignalHandlerFn fn) {
+    special_handler_ = fn;
+  }
+
+  SpecialSignalHandlerFn GetSpecialHandler() {
+    return special_handler_;
+  }
+
  private:
-  struct sigaction action_;     // Action to be performed.
-  bool claimed_;                // Whether signal is claimed or not.
-  bool uses_old_style_;         // Action is created using signal().  Use sa_handler.
+  struct sigaction action_;                 // Action to be performed.
+  bool claimed_;                            // Whether signal is claimed or not.
+  bool uses_old_style_;                     // Action is created using signal().  Use sa_handler.
+  SpecialSignalHandlerFn special_handler_;  // A special handler executed before user handlers.
 };
 
 // User's signal handlers
@@ -109,9 +118,16 @@
   }
 }
 
+// Sigchainlib's own handler so we can ensure a managed handler is called first even if nobody
+// claimed a chain. Simply forward to InvokeUserSignalHandler.
+static void sigchainlib_managed_handler_sigaction(int sig, siginfo_t* info, void* context) {
+  InvokeUserSignalHandler(sig, info, context);
+}
+
 // Claim a signal chain for a particular signal.
 extern "C" void ClaimSignalChain(int signal, struct sigaction* oldaction) {
   CheckSignalValid(signal);
+
   user_sigactions[signal].Claim(*oldaction);
 }
 
@@ -131,6 +147,15 @@
     abort();
   }
 
+  // Do we have a managed handler? If so, run it first.
+  SpecialSignalHandlerFn managed = user_sigactions[sig].GetSpecialHandler();
+  if (managed != nullptr) {
+    // Call the handler. If it succeeds, we're done.
+    if (managed(sig, info, context)) {
+      return;
+    }
+  }
+
   const struct sigaction& action = user_sigactions[sig].GetAction();
   if (user_sigactions[sig].OldStyle()) {
     if (action.sa_handler != nullptr) {
@@ -303,5 +328,25 @@
   initialized = true;
 }
 
+extern "C" void SetSpecialSignalHandlerFn(int signal, SpecialSignalHandlerFn fn) {
+  CheckSignalValid(signal);
+
+  // Set the managed_handler.
+  user_sigactions[signal].SetSpecialHandler(fn);
+
+  // In case the chain isn't claimed, claim it for ourself so we can ensure the managed handler
+  // goes first.
+  if (!user_sigactions[signal].IsClaimed()) {
+    struct sigaction tmp;
+    tmp.sa_sigaction = sigchainlib_managed_handler_sigaction;
+    sigemptyset(&tmp.sa_mask);
+    tmp.sa_flags = SA_SIGINFO | SA_ONSTACK;
+#if !defined(__APPLE__) && !defined(__mips__)
+    tmp.sa_restorer = nullptr;
+#endif
+    user_sigactions[signal].Claim(tmp);
+  }
+}
+
 }   // namespace art
 
diff --git a/sigchainlib/sigchain.h b/sigchainlib/sigchain.h
index 79b76a7..01ccedf 100644
--- a/sigchainlib/sigchain.h
+++ b/sigchainlib/sigchain.h
@@ -27,6 +27,9 @@
 
 extern "C" void UnclaimSignalChain(int signal);
 
+typedef bool (*SpecialSignalHandlerFn)(int, siginfo_t*, void*);
+extern "C" void SetSpecialSignalHandlerFn(int signal, SpecialSignalHandlerFn fn);
+
 extern "C" void InvokeUserSignalHandler(int sig, siginfo_t* info, void* context);
 
 extern "C" void EnsureFrontOfChain(int signal, struct sigaction* expected_action);
diff --git a/sigchainlib/sigchain_dummy.cc b/sigchainlib/sigchain_dummy.cc
index 70a4f71..8495a54 100644
--- a/sigchainlib/sigchain_dummy.cc
+++ b/sigchainlib/sigchain_dummy.cc
@@ -78,6 +78,12 @@
   abort();
 }
 
+extern "C" void SetSpecialSignalHandlerFn(int signal ATTRIBUTE_UNUSED,
+                                          SpecialSignalHandlerFn fn ATTRIBUTE_UNUSED) {
+  log("SetSpecialSignalHandlerFn is not exported by the main executable.");
+  abort();
+}
+
 #pragma GCC diagnostic pop
 
 }  // namespace art
diff --git a/test/004-JniTest/jni_test.cc b/test/004-JniTest/jni_test.cc
index 1ec0cf2..71a2b2d 100644
--- a/test/004-JniTest/jni_test.cc
+++ b/test/004-JniTest/jni_test.cc
@@ -604,4 +604,20 @@
   args4[0].l = string_arg;
   env->CallVoidMethodA(s3, mid3, args3);
   env->CallNonvirtualVoidMethodA(s4, c, mid4, args4);
+
+  // Test with global and weak global references
+  jstring s5 = reinterpret_cast<jstring>(env->AllocObject(c));
+  assert(s5 != nullptr);
+  s5 = reinterpret_cast<jstring>(env->NewGlobalRef(s5));
+  jstring s6 = reinterpret_cast<jstring>(env->AllocObject(c));
+  assert(s6 != nullptr);
+  s6 = reinterpret_cast<jstring>(env->NewWeakGlobalRef(s6));
+
+  env->CallVoidMethod(s5, mid1);
+  env->CallNonvirtualVoidMethod(s6, c, mid2, byte_array);
+  assert(env->GetStringLength(s5) == 0);
+  assert(env->GetStringLength(s6) == byte_array_length);
+  const char* chars6 = env->GetStringUTFChars(s6, nullptr);
+  assert(strcmp(test_array, chars6) == 0);
+  env->ReleaseStringUTFChars(s6, chars6);
 }
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/src/Main.java b/test/004-StackWalk/src/Main.java
index 1e2a91b..782f51d 100644
--- a/test/004-StackWalk/src/Main.java
+++ b/test/004-StackWalk/src/Main.java
@@ -2,9 +2,14 @@
   public Main() {
   }
 
-  int f() {
+  int f() throws Exception {
     g(1);
     g(2);
+
+    // This loop currently defeats inlining of `f`.
+    for (int i = 0; i < 10; i++) {
+      Thread.sleep(0);
+    }
     return 0;
   }
 
@@ -86,7 +91,7 @@
     System.loadLibrary("arttest");
   }
 
-  public static void main(String[] args) {
+  public static void main(String[] args) throws Exception {
     Main st = new Main();
     st.f();
   }
diff --git a/test/004-StackWalk/stack_walk_jni.cc b/test/004-StackWalk/stack_walk_jni.cc
index c40de7e..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,
@@ -45,11 +45,11 @@
     if (m_name == "f") {
       if (gJava_StackWalk_refmap_calls == 1) {
         CHECK_EQ(1U, GetDexPc());
-        CHECK_REGS(1);
+        CHECK_REGS(4);
       } else {
         CHECK_EQ(gJava_StackWalk_refmap_calls, 2);
         CHECK_EQ(5U, GetDexPc());
-        CHECK_REGS(1);
+        CHECK_REGS(4);
       }
     } else if (m_name == "g") {
       if (gJava_StackWalk_refmap_calls == 1) {
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/115-native-bridge/expected.txt b/test/115-native-bridge/expected.txt
index deb70ba..464d2c8 100644
--- a/test/115-native-bridge/expected.txt
+++ b/test/115-native-bridge/expected.txt
@@ -4,7 +4,7 @@
 Ready for native bridge tests.
 Checking for support.
 Getting trampoline for JNI_OnLoad with shorty (null).
-Test ART callbacks: all JNI function number is 10.
+Test ART callbacks: all JNI function number is 11.
     name:booleanMethod, signature:(ZZZZZZZZZZ)Z, shorty:ZZZZZZZZZZZ.
     name:byteMethod, signature:(BBBBBBBBBB)B, shorty:BBBBBBBBBBB.
     name:charMethod, signature:(CCCCCCCCCC)C, shorty:CCCCCCCCCCC.
@@ -14,6 +14,7 @@
     name:testFindFieldOnAttachedNativeThreadNative, signature:()V, shorty:V.
     name:testGetMirandaMethodNative, signature:()Ljava/lang/reflect/Method;, shorty:L.
     name:testNewStringObject, signature:()V, shorty:V.
+    name:testSignal, signature:()I, shorty:I.
     name:testZeroLengthByteBuffers, signature:()V, shorty:V.
 trampoline_JNI_OnLoad called!
 Getting trampoline for Java_Main_testFindClassOnAttachedNativeThread with shorty V.
@@ -58,3 +59,5 @@
 trampoline_Java_Main_charMethod called!
 Getting trampoline for Java_Main_testNewStringObject with shorty V.
 trampoline_Java_Main_testNewStringObject called!
+Getting trampoline for Java_Main_testSignal with shorty I.
+NB signal handler with signal 11.
diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc
index db2fc9b..c8141a7 100644
--- a/test/115-native-bridge/nativebridge.cc
+++ b/test/115-native-bridge/nativebridge.cc
@@ -19,6 +19,8 @@
 #include <algorithm>
 #include <dlfcn.h>
 #include <jni.h>
+#include <stdlib.h>
+#include <signal.h>
 #include <vector>
 
 #include "stdio.h"
@@ -179,6 +181,37 @@
   return fnPtr(env, klass, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10);
 }
 
+// This code is adapted from 004-SignalTest and causes a segfault.
+char *go_away_compiler = nullptr;
+
+[[ noreturn ]] static void test_sigaction_handler(int sig ATTRIBUTE_UNUSED,
+                                                  siginfo_t* info ATTRIBUTE_UNUSED,
+                                                  void* context ATTRIBUTE_UNUSED) {
+  printf("Should not reach the test sigaction handler.");
+  abort();
+}
+
+static jint trampoline_Java_Main_testSignal(JNIEnv*, jclass) {
+  // Install the sigaction handler above, which should *not* be reached as the native-bridge
+  // handler should be called first. Note: we won't chain at all, if we ever get here, we'll die.
+  struct sigaction tmp;
+  sigemptyset(&tmp.sa_mask);
+  tmp.sa_sigaction = test_sigaction_handler;
+#if !defined(__APPLE__) && !defined(__mips__)
+  tmp.sa_restorer = nullptr;
+#endif
+  sigaction(SIGSEGV, &tmp, nullptr);
+
+#if defined(__arm__) || defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
+  // On supported architectures we cause a real SEGV.
+  *go_away_compiler = 'a';
+#else
+  // On other architectures we simulate SEGV.
+  kill(getpid(), SIGSEGV);
+#endif
+  return 1234;
+}
+
 NativeBridgeMethod gNativeBridgeMethods[] = {
   { "JNI_OnLoad", "", true, nullptr,
     reinterpret_cast<void*>(trampoline_JNI_OnLoad) },
@@ -202,6 +235,8 @@
     reinterpret_cast<void*>(trampoline_Java_Main_testNewStringObject) },
   { "testZeroLengthByteBuffers", "()V", true, nullptr,
     reinterpret_cast<void*>(trampoline_Java_Main_testZeroLengthByteBuffers) },
+  { "testSignal", "()I", true, nullptr,
+    reinterpret_cast<void*>(trampoline_Java_Main_testSignal) },
 };
 
 static NativeBridgeMethod* find_native_bridge_method(const char *name) {
@@ -319,15 +354,73 @@
   return &nb_env;
 }
 
+// v2 parts.
+
+extern "C" bool nb_is_compatible(uint32_t bridge_version ATTRIBUTE_UNUSED) {
+  return true;
+}
+
+#if defined(__i386__) || defined(__x86_64__)
+#if defined(__APPLE__)
+#define ucontext __darwin_ucontext
+
+#if defined(__x86_64__)
+// 64 bit mac build.
+#define CTX_EIP uc_mcontext->__ss.__rip
+#else
+// 32 bit mac build.
+#define CTX_EIP uc_mcontext->__ss.__eip
+#endif
+
+#elif defined(__x86_64__)
+// 64 bit linux build.
+#define CTX_EIP uc_mcontext.gregs[REG_RIP]
+#else
+// 32 bit linux build.
+#define CTX_EIP uc_mcontext.gregs[REG_EIP]
+#endif
+#endif
+
+// A dummy special handler, continueing after the faulting location. This code comes from
+// 004-SignalTest.
+static bool nb_signalhandler(int sig, siginfo_t* info ATTRIBUTE_UNUSED, void* context) {
+  printf("NB signal handler with signal %d.\n", sig);
+#if defined(__arm__)
+  struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
+  struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
+  sc->arm_pc += 2;          // Skip instruction causing segv.
+#elif defined(__aarch64__)
+  struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
+  struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
+  sc->pc += 4;          // Skip instruction causing segv.
+#elif defined(__i386__) || defined(__x86_64__)
+  struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
+  uc->CTX_EIP += 3;
+#else
+  UNUSED(context);
+#endif
+  // We handled this...
+  return true;
+}
+
+static ::android::NativeBridgeSignalHandlerFn native_bridge_get_signal_handler(int signal) {
+  // Only test segfault handler.
+  if (signal == SIGSEGV) {
+    return &nb_signalhandler;
+  }
+  return nullptr;
+}
+
+
 // "NativeBridgeItf" is effectively an API (it is the name of the symbol that will be loaded
 // by the native bridge library).
 android::NativeBridgeCallbacks NativeBridgeItf {
-  .version = 1,
+  .version = 2,
   .initialize = &native_bridge_initialize,
   .loadLibrary = &native_bridge_loadLibrary,
   .getTrampoline = &native_bridge_getTrampoline,
   .isSupported = &native_bridge_isSupported,
   .getAppEnv = &native_bridge_getAppEnv,
-  .isCompatibleWith = nullptr,
-  .getSignalHandler = nullptr
+  .isCompatibleWith = &nb_is_compatible,
+  .getSignalHandler = &native_bridge_get_signal_handler
 };
diff --git a/test/115-native-bridge/src/NativeBridgeMain.java b/test/115-native-bridge/src/NativeBridgeMain.java
index c843707..25390f7 100644
--- a/test/115-native-bridge/src/NativeBridgeMain.java
+++ b/test/115-native-bridge/src/NativeBridgeMain.java
@@ -32,6 +32,7 @@
         testCharMethod();
         testEnvironment();
         testNewStringObject();
+        testSignalHandler();
     }
 
     public static native void testFindClassOnAttachedNativeThread();
@@ -170,6 +171,18 @@
     }
 
     private static native void testNewStringObject();
+
+    // Test v2 special signal handlers. This uses the native code from 004-SignalTest to cause
+    // a non-managed segfault.
+    private static void testSignalHandler() {
+        // This uses code from 004-SignalTest.
+        int x = testSignal();
+        if (x != 1234) {
+            throw new AssertionError();
+        }
+    }
+
+    private static native int testSignal();
 }
 
 public class NativeBridgeMain {
diff --git a/test/441-checker-inliner/src/Main.java b/test/441-checker-inliner/src/Main.java
index 8894d4e..df969a4 100644
--- a/test/441-checker-inliner/src/Main.java
+++ b/test/441-checker-inliner/src/Main.java
@@ -16,133 +16,133 @@
 
 public class Main {
 
-  // CHECK-START: void Main.InlineVoid() inliner (before)
-  // CHECK-DAG:     <<Const42:i\d+>> IntConstant 42
-  // CHECK-DAG:                      InvokeStaticOrDirect
-  // CHECK-DAG:                      InvokeStaticOrDirect [<<Const42>>]
+  /// CHECK-START: void Main.InlineVoid() inliner (before)
+  /// CHECK-DAG:     <<Const42:i\d+>> IntConstant 42
+  /// CHECK-DAG:                      InvokeStaticOrDirect
+  /// CHECK-DAG:                      InvokeStaticOrDirect [<<Const42>>]
 
-  // CHECK-START: void Main.InlineVoid() inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: void Main.InlineVoid() inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
   public static void InlineVoid() {
     returnVoid();
     returnVoidWithOneParameter(42);
   }
 
-  // CHECK-START: int Main.InlineParameter(int) inliner (before)
-  // CHECK-DAG:     <<Param:i\d+>>  ParameterValue
-  // CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect [<<Param>>]
-  // CHECK-DAG:                     Return [<<Result>>]
+  /// CHECK-START: int Main.InlineParameter(int) inliner (before)
+  /// CHECK-DAG:     <<Param:i\d+>>  ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect [<<Param>>]
+  /// CHECK-DAG:                     Return [<<Result>>]
 
-  // CHECK-START: int Main.InlineParameter(int) inliner (after)
-  // CHECK-DAG:     <<Param:i\d+>>  ParameterValue
-  // CHECK-DAG:                     Return [<<Param>>]
+  /// CHECK-START: int Main.InlineParameter(int) inliner (after)
+  /// CHECK-DAG:     <<Param:i\d+>>  ParameterValue
+  /// CHECK-DAG:                     Return [<<Param>>]
 
   public static int InlineParameter(int a) {
     return returnParameter(a);
   }
 
-  // CHECK-START: long Main.InlineWideParameter(long) inliner (before)
-  // CHECK-DAG:     <<Param:j\d+>>  ParameterValue
-  // CHECK-DAG:     <<Result:j\d+>> InvokeStaticOrDirect [<<Param>>]
-  // CHECK-DAG:                     Return [<<Result>>]
+  /// CHECK-START: long Main.InlineWideParameter(long) inliner (before)
+  /// CHECK-DAG:     <<Param:j\d+>>  ParameterValue
+  /// CHECK-DAG:     <<Result:j\d+>> InvokeStaticOrDirect [<<Param>>]
+  /// CHECK-DAG:                     Return [<<Result>>]
 
-  // CHECK-START: long Main.InlineWideParameter(long) inliner (after)
-  // CHECK-DAG:     <<Param:j\d+>>  ParameterValue
-  // CHECK-DAG:                     Return [<<Param>>]
+  /// CHECK-START: long Main.InlineWideParameter(long) inliner (after)
+  /// CHECK-DAG:     <<Param:j\d+>>  ParameterValue
+  /// CHECK-DAG:                     Return [<<Param>>]
 
   public static long InlineWideParameter(long a) {
     return returnWideParameter(a);
   }
 
-  // CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (before)
-  // CHECK-DAG:     <<Param:l\d+>>  ParameterValue
-  // CHECK-DAG:     <<Result:l\d+>> InvokeStaticOrDirect [<<Param>>]
-  // CHECK-DAG:                     Return [<<Result>>]
+  /// CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (before)
+  /// CHECK-DAG:     <<Param:l\d+>>  ParameterValue
+  /// CHECK-DAG:     <<Result:l\d+>> InvokeStaticOrDirect [<<Param>>]
+  /// CHECK-DAG:                     Return [<<Result>>]
 
-  // CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (after)
-  // CHECK-DAG:     <<Param:l\d+>>  ParameterValue
-  // CHECK-DAG:                     Return [<<Param>>]
+  /// CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (after)
+  /// CHECK-DAG:     <<Param:l\d+>>  ParameterValue
+  /// CHECK-DAG:                     Return [<<Param>>]
 
   public static Object InlineReferenceParameter(Object o) {
     return returnReferenceParameter(o);
   }
 
-  // CHECK-START: int Main.InlineInt() inliner (before)
-  // CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [<<Result>>]
+  /// CHECK-START: int Main.InlineInt() inliner (before)
+  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect
+  /// CHECK-DAG:                     Return [<<Result>>]
 
-  // CHECK-START: int Main.InlineInt() inliner (after)
-  // CHECK-DAG:     <<Const4:i\d+>> IntConstant 4
-  // CHECK-DAG:                     Return [<<Const4>>]
+  /// CHECK-START: int Main.InlineInt() inliner (after)
+  /// CHECK-DAG:     <<Const4:i\d+>> IntConstant 4
+  /// CHECK-DAG:                     Return [<<Const4>>]
 
   public static int InlineInt() {
     return returnInt();
   }
 
-  // CHECK-START: long Main.InlineWide() inliner (before)
-  // CHECK-DAG:     <<Result:j\d+>> InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [<<Result>>]
+  /// CHECK-START: long Main.InlineWide() inliner (before)
+  /// CHECK-DAG:     <<Result:j\d+>> InvokeStaticOrDirect
+  /// CHECK-DAG:                     Return [<<Result>>]
 
-  // CHECK-START: long Main.InlineWide() inliner (after)
-  // CHECK-DAG:     <<Const8:j\d+>> LongConstant 8
-  // CHECK-DAG:                     Return [<<Const8>>]
+  /// CHECK-START: long Main.InlineWide() inliner (after)
+  /// CHECK-DAG:     <<Const8:j\d+>> LongConstant 8
+  /// CHECK-DAG:                     Return [<<Const8>>]
 
   public static long InlineWide() {
     return returnWide();
   }
 
-  // CHECK-START: int Main.InlineAdd() inliner (before)
-  // CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
-  // CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
-  // CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [<<Result>>]
+  /// CHECK-START: int Main.InlineAdd() inliner (before)
+  /// CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
+  /// CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
+  /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect
+  /// CHECK-DAG:                     Return [<<Result>>]
 
-  // CHECK-START: int Main.InlineAdd() inliner (after)
-  // CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
-  // CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
-  // CHECK-DAG:     <<Add:i\d+>>    Add [<<Const3>>,<<Const5>>]
-  // CHECK-DAG:                     Return [<<Add>>]
+  /// CHECK-START: int Main.InlineAdd() inliner (after)
+  /// CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
+  /// CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
+  /// CHECK-DAG:     <<Add:i\d+>>    Add [<<Const3>>,<<Const5>>]
+  /// CHECK-DAG:                     Return [<<Add>>]
 
   public static int InlineAdd() {
     return returnAdd(3, 5);
   }
 
-  // CHECK-START: int Main.InlineFieldAccess() inliner (before)
-  // CHECK-DAG:     <<After:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                     Return [<<After>>]
+  /// CHECK-START: int Main.InlineFieldAccess() inliner (before)
+  /// CHECK-DAG:     <<After:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                     Return [<<After>>]
 
-  // CHECK-START: int Main.InlineFieldAccess() inliner (after)
-  // CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
-  // CHECK-DAG:     <<Before:i\d+>> StaticFieldGet
-  // CHECK-DAG:     <<After:i\d+>>  Add [<<Before>>,<<Const1>>]
-  // CHECK-DAG:                     StaticFieldSet [{{l\d+}},<<After>>]
-  // CHECK-DAG:                     Return [<<After>>]
+  /// CHECK-START: int Main.InlineFieldAccess() inliner (after)
+  /// CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
+  /// CHECK-DAG:     <<Before:i\d+>> StaticFieldGet
+  /// CHECK-DAG:     <<After:i\d+>>  Add [<<Before>>,<<Const1>>]
+  /// CHECK-DAG:                     StaticFieldSet [{{l\d+}},<<After>>]
+  /// CHECK-DAG:                     Return [<<After>>]
 
-  // CHECK-START: int Main.InlineFieldAccess() inliner (after)
-  // CHECK-NOT:                     InvokeStaticOrDirect
+  /// CHECK-START: int Main.InlineFieldAccess() inliner (after)
+  /// CHECK-NOT:                     InvokeStaticOrDirect
 
   public static int InlineFieldAccess() {
     return incCounter();
   }
 
-  // CHECK-START: int Main.InlineWithControlFlow(boolean) inliner (before)
-  // CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
-  // CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
-  // CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
-  // CHECK-DAG:     <<Add:i\d+>>    InvokeStaticOrDirect [<<Const1>>,<<Const3>>]
-  // CHECK-DAG:     <<Sub:i\d+>>    InvokeStaticOrDirect [<<Const5>>,<<Const3>>]
-  // CHECK-DAG:     <<Phi:i\d+>>    Phi [<<Add>>,<<Sub>>]
-  // CHECK-DAG:                     Return [<<Phi>>]
+  /// CHECK-START: int Main.InlineWithControlFlow(boolean) inliner (before)
+  /// CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
+  /// CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
+  /// CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
+  /// CHECK-DAG:     <<Add:i\d+>>    InvokeStaticOrDirect [<<Const1>>,<<Const3>>]
+  /// CHECK-DAG:     <<Sub:i\d+>>    InvokeStaticOrDirect [<<Const5>>,<<Const3>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>    Phi [<<Add>>,<<Sub>>]
+  /// CHECK-DAG:                     Return [<<Phi>>]
 
-  // CHECK-START: int Main.InlineWithControlFlow(boolean) inliner (after)
-  // CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
-  // CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
-  // CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
-  // CHECK-DAG:     <<Add:i\d+>>    Add [<<Const1>>,<<Const3>>]
-  // CHECK-DAG:     <<Sub:i\d+>>    Sub [<<Const5>>,<<Const3>>]
-  // CHECK-DAG:     <<Phi:i\d+>>    Phi [<<Add>>,<<Sub>>]
-  // CHECK-DAG:                     Return [<<Phi>>]
+  /// CHECK-START: int Main.InlineWithControlFlow(boolean) inliner (after)
+  /// CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
+  /// CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
+  /// CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
+  /// CHECK-DAG:     <<Add:i\d+>>    Add [<<Const1>>,<<Const3>>]
+  /// CHECK-DAG:     <<Sub:i\d+>>    Sub [<<Const5>>,<<Const3>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>    Phi [<<Add>>,<<Sub>>]
+  /// CHECK-DAG:                     Return [<<Phi>>]
 
   public static int InlineWithControlFlow(boolean cond) {
     int x, const1, const3, const5;
diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java
index c258db9..b7863be 100644
--- a/test/442-checker-constant-folding/src/Main.java
+++ b/test/442-checker-constant-folding/src/Main.java
@@ -51,14 +51,14 @@
    * on negation.
    */
 
-  // CHECK-START: int Main.IntNegation() constant_folding (before)
-  // CHECK-DAG:     <<Const42:i\d+>>  IntConstant 42
-  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Const42>>]
-  // CHECK-DAG:                       Return [<<Neg>>]
+  /// CHECK-START: int Main.IntNegation() constant_folding (before)
+  /// CHECK-DAG:     <<Const42:i\d+>>  IntConstant 42
+  /// CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Const42>>]
+  /// CHECK-DAG:                       Return [<<Neg>>]
 
-  // CHECK-START: int Main.IntNegation() constant_folding (after)
-  // CHECK-DAG:     <<ConstN42:i\d+>> IntConstant -42
-  // CHECK-DAG:                       Return [<<ConstN42>>]
+  /// CHECK-START: int Main.IntNegation() constant_folding (after)
+  /// CHECK-DAG:     <<ConstN42:i\d+>> IntConstant -42
+  /// CHECK-DAG:                       Return [<<ConstN42>>]
 
   public static int IntNegation() {
     int x, y;
@@ -72,15 +72,15 @@
    * on addition.
    */
 
-  // CHECK-START: int Main.IntAddition1() constant_folding (before)
-  // CHECK-DAG:     <<Const1:i\d+>>  IntConstant 1
-  // CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
-  // CHECK-DAG:     <<Add:i\d+>>     Add [<<Const1>>,<<Const2>>]
-  // CHECK-DAG:                      Return [<<Add>>]
+  /// CHECK-START: int Main.IntAddition1() constant_folding (before)
+  /// CHECK-DAG:     <<Const1:i\d+>>  IntConstant 1
+  /// CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
+  /// CHECK-DAG:     <<Add:i\d+>>     Add [<<Const1>>,<<Const2>>]
+  /// CHECK-DAG:                      Return [<<Add>>]
 
-  // CHECK-START: int Main.IntAddition1() constant_folding (after)
-  // CHECK-DAG:     <<Const3:i\d+>>  IntConstant 3
-  // CHECK-DAG:                      Return [<<Const3>>]
+  /// CHECK-START: int Main.IntAddition1() constant_folding (after)
+  /// CHECK-DAG:     <<Const3:i\d+>>  IntConstant 3
+  /// CHECK-DAG:                      Return [<<Const3>>]
 
   public static int IntAddition1() {
     int a, b, c;
@@ -95,19 +95,19 @@
   * on addition.
   */
 
-  // CHECK-START: int Main.IntAddition2() constant_folding (before)
-  // CHECK-DAG:     <<Const1:i\d+>>  IntConstant 1
-  // CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
-  // CHECK-DAG:     <<Const5:i\d+>>  IntConstant 5
-  // CHECK-DAG:     <<Const6:i\d+>>  IntConstant 6
-  // CHECK-DAG:     <<Add1:i\d+>>    Add [<<Const1>>,<<Const2>>]
-  // CHECK-DAG:     <<Add2:i\d+>>    Add [<<Const5>>,<<Const6>>]
-  // CHECK-DAG:     <<Add3:i\d+>>    Add [<<Add1>>,<<Add2>>]
-  // CHECK-DAG:                      Return [<<Add3>>]
+  /// CHECK-START: int Main.IntAddition2() constant_folding (before)
+  /// CHECK-DAG:     <<Const1:i\d+>>  IntConstant 1
+  /// CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
+  /// CHECK-DAG:     <<Const5:i\d+>>  IntConstant 5
+  /// CHECK-DAG:     <<Const6:i\d+>>  IntConstant 6
+  /// CHECK-DAG:     <<Add1:i\d+>>    Add [<<Const1>>,<<Const2>>]
+  /// CHECK-DAG:     <<Add2:i\d+>>    Add [<<Const5>>,<<Const6>>]
+  /// CHECK-DAG:     <<Add3:i\d+>>    Add [<<Add1>>,<<Add2>>]
+  /// CHECK-DAG:                      Return [<<Add3>>]
 
-  // CHECK-START: int Main.IntAddition2() constant_folding (after)
-  // CHECK-DAG:     <<Const14:i\d+>> IntConstant 14
-  // CHECK-DAG:                      Return [<<Const14>>]
+  /// CHECK-START: int Main.IntAddition2() constant_folding (after)
+  /// CHECK-DAG:     <<Const14:i\d+>> IntConstant 14
+  /// CHECK-DAG:                      Return [<<Const14>>]
 
   public static int IntAddition2() {
     int a, b, c;
@@ -126,15 +126,15 @@
    * on subtraction.
    */
 
-  // CHECK-START: int Main.IntSubtraction() constant_folding (before)
-  // CHECK-DAG:     <<Const6:i\d+>>  IntConstant 6
-  // CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
-  // CHECK-DAG:     <<Sub:i\d+>>     Sub [<<Const6>>,<<Const2>>]
-  // CHECK-DAG:                      Return [<<Sub>>]
+  /// CHECK-START: int Main.IntSubtraction() constant_folding (before)
+  /// CHECK-DAG:     <<Const6:i\d+>>  IntConstant 6
+  /// CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
+  /// CHECK-DAG:     <<Sub:i\d+>>     Sub [<<Const6>>,<<Const2>>]
+  /// CHECK-DAG:                      Return [<<Sub>>]
 
-  // CHECK-START: int Main.IntSubtraction() constant_folding (after)
-  // CHECK-DAG:     <<Const4:i\d+>>  IntConstant 4
-  // CHECK-DAG:                      Return [<<Const4>>]
+  /// CHECK-START: int Main.IntSubtraction() constant_folding (after)
+  /// CHECK-DAG:     <<Const4:i\d+>>  IntConstant 4
+  /// CHECK-DAG:                      Return [<<Const4>>]
 
   public static int IntSubtraction() {
     int a, b, c;
@@ -149,15 +149,15 @@
    * on addition.
    */
 
-  // CHECK-START: long Main.LongAddition() constant_folding (before)
-  // CHECK-DAG:     <<Const1:j\d+>>  LongConstant 1
-  // CHECK-DAG:     <<Const2:j\d+>>  LongConstant 2
-  // CHECK-DAG:     <<Add:j\d+>>     Add [<<Const1>>,<<Const2>>]
-  // CHECK-DAG:                      Return [<<Add>>]
+  /// CHECK-START: long Main.LongAddition() constant_folding (before)
+  /// CHECK-DAG:     <<Const1:j\d+>>  LongConstant 1
+  /// CHECK-DAG:     <<Const2:j\d+>>  LongConstant 2
+  /// CHECK-DAG:     <<Add:j\d+>>     Add [<<Const1>>,<<Const2>>]
+  /// CHECK-DAG:                      Return [<<Add>>]
 
-  // CHECK-START: long Main.LongAddition() constant_folding (after)
-  // CHECK-DAG:     <<Const3:j\d+>>  LongConstant 3
-  // CHECK-DAG:                      Return [<<Const3>>]
+  /// CHECK-START: long Main.LongAddition() constant_folding (after)
+  /// CHECK-DAG:     <<Const3:j\d+>>  LongConstant 3
+  /// CHECK-DAG:                      Return [<<Const3>>]
 
   public static long LongAddition() {
     long a, b, c;
@@ -172,15 +172,15 @@
    * on subtraction.
    */
 
-  // CHECK-START: long Main.LongSubtraction() constant_folding (before)
-  // CHECK-DAG:     <<Const6:j\d+>>  LongConstant 6
-  // CHECK-DAG:     <<Const2:j\d+>>  LongConstant 2
-  // CHECK-DAG:     <<Sub:j\d+>>     Sub [<<Const6>>,<<Const2>>]
-  // CHECK-DAG:                      Return [<<Sub>>]
+  /// CHECK-START: long Main.LongSubtraction() constant_folding (before)
+  /// CHECK-DAG:     <<Const6:j\d+>>  LongConstant 6
+  /// CHECK-DAG:     <<Const2:j\d+>>  LongConstant 2
+  /// CHECK-DAG:     <<Sub:j\d+>>     Sub [<<Const6>>,<<Const2>>]
+  /// CHECK-DAG:                      Return [<<Sub>>]
 
-  // CHECK-START: long Main.LongSubtraction() constant_folding (after)
-  // CHECK-DAG:     <<Const4:j\d+>>  LongConstant 4
-  // CHECK-DAG:                      Return [<<Const4>>]
+  /// CHECK-START: long Main.LongSubtraction() constant_folding (after)
+  /// CHECK-DAG:     <<Const4:j\d+>>  LongConstant 4
+  /// CHECK-DAG:                      Return [<<Const4>>]
 
   public static long LongSubtraction() {
     long a, b, c;
@@ -194,15 +194,15 @@
    * Three-register program with a constant (static) condition.
    */
 
-  // CHECK-START: int Main.StaticCondition() constant_folding (before)
-  // CHECK-DAG:     <<Const7:i\d+>>  IntConstant 7
-  // CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
-  // CHECK-DAG:     <<Cond:z\d+>>    GreaterThanOrEqual [<<Const7>>,<<Const2>>]
-  // CHECK-DAG:                      If [<<Cond>>]
+  /// CHECK-START: int Main.StaticCondition() constant_folding (before)
+  /// CHECK-DAG:     <<Const7:i\d+>>  IntConstant 7
+  /// CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
+  /// CHECK-DAG:     <<Cond:z\d+>>    GreaterThanOrEqual [<<Const7>>,<<Const2>>]
+  /// CHECK-DAG:                      If [<<Cond>>]
 
-  // CHECK-START: int Main.StaticCondition() constant_folding (after)
-  // CHECK-DAG:     <<Const1:i\d+>>  IntConstant 1
-  // CHECK-DAG:                      If [<<Const1>>]
+  /// CHECK-START: int Main.StaticCondition() constant_folding (after)
+  /// CHECK-DAG:     <<Const1:i\d+>>  IntConstant 1
+  /// CHECK-DAG:                      If [<<Const1>>]
 
   public static int StaticCondition() {
     int a, b, c;
@@ -224,19 +224,19 @@
    * (forward) post-order traversal of the the dominator tree.
    */
 
-  // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (before)
-  // CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
-  // CHECK-DAG:     <<Const5:i\d+>>  IntConstant 5
-  // CHECK-DAG:     <<Add:i\d+>>     Add [<<Const5>>,<<Const2>>]
-  // CHECK-DAG:     <<Sub:i\d+>>     Sub [<<Const5>>,<<Const2>>]
-  // CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
-  // CHECK-DAG:                      Return [<<Phi>>]
+  /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (before)
+  /// CHECK-DAG:     <<Const2:i\d+>>  IntConstant 2
+  /// CHECK-DAG:     <<Const5:i\d+>>  IntConstant 5
+  /// CHECK-DAG:     <<Add:i\d+>>     Add [<<Const5>>,<<Const2>>]
+  /// CHECK-DAG:     <<Sub:i\d+>>     Sub [<<Const5>>,<<Const2>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
+  /// CHECK-DAG:                      Return [<<Phi>>]
 
-  // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after)
-  // CHECK-DAG:     <<Const3:i\d+>>  IntConstant 3
-  // CHECK-DAG:     <<Const7:i\d+>>  IntConstant 7
-  // CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Const7>>,<<Const3>>]
-  // CHECK-DAG:                      Return [<<Phi>>]
+  /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after)
+  /// CHECK-DAG:     <<Const3:i\d+>>  IntConstant 3
+  /// CHECK-DAG:     <<Const7:i\d+>>  IntConstant 7
+  /// CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Const7>>,<<Const3>>]
+  /// CHECK-DAG:                      Return [<<Phi>>]
 
   public static int JumpsAndConditionals(boolean cond) {
     int a, b, c;
@@ -253,388 +253,388 @@
    * Test optimizations of arithmetic identities yielding a constant result.
    */
 
-  // CHECK-START: int Main.And0(int) constant_folding (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<And:i\d+>>      And [<<Arg>>,<<Const0>>]
-  // CHECK-DAG:                       Return [<<And>>]
+  /// CHECK-START: int Main.And0(int) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<And:i\d+>>      And [<<Arg>>,<<Const0>>]
+  /// CHECK-DAG:                       Return [<<And>>]
 
-  // CHECK-START: int Main.And0(int) constant_folding (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-NOT:                       And
-  // CHECK-DAG:                       Return [<<Const0>>]
+  /// CHECK-START: int Main.And0(int) constant_folding (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-NOT:                       And
+  /// CHECK-DAG:                       Return [<<Const0>>]
 
   public static int And0(int arg) {
     return arg & 0;
   }
 
-  // CHECK-START: long Main.Mul0(long) constant_folding (before)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
-  // CHECK-DAG:     <<Mul:j\d+>>      Mul [<<Arg>>,<<Const0>>]
-  // CHECK-DAG:                       Return [<<Mul>>]
+  /// CHECK-START: long Main.Mul0(long) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  /// CHECK-DAG:     <<Mul:j\d+>>      Mul [<<Arg>>,<<Const0>>]
+  /// CHECK-DAG:                       Return [<<Mul>>]
 
-  // CHECK-START: long Main.Mul0(long) constant_folding (after)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
-  // CHECK-NOT:                       Mul
-  // CHECK-DAG:                       Return [<<Const0>>]
+  /// CHECK-START: long Main.Mul0(long) constant_folding (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  /// CHECK-NOT:                       Mul
+  /// CHECK-DAG:                       Return [<<Const0>>]
 
   public static long Mul0(long arg) {
     return arg * 0;
   }
 
-  // CHECK-START: int Main.OrAllOnes(int) constant_folding (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<ConstF:i\d+>>   IntConstant -1
-  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Arg>>,<<ConstF>>]
-  // CHECK-DAG:                       Return [<<Or>>]
+  /// CHECK-START: int Main.OrAllOnes(int) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<ConstF:i\d+>>   IntConstant -1
+  /// CHECK-DAG:     <<Or:i\d+>>       Or [<<Arg>>,<<ConstF>>]
+  /// CHECK-DAG:                       Return [<<Or>>]
 
-  // CHECK-START: int Main.OrAllOnes(int) constant_folding (after)
-  // CHECK-DAG:     <<ConstF:i\d+>>   IntConstant -1
-  // CHECK-NOT:                       Or
-  // CHECK-DAG:                       Return [<<ConstF>>]
+  /// CHECK-START: int Main.OrAllOnes(int) constant_folding (after)
+  /// CHECK-DAG:     <<ConstF:i\d+>>   IntConstant -1
+  /// CHECK-NOT:                       Or
+  /// CHECK-DAG:                       Return [<<ConstF>>]
 
   public static int OrAllOnes(int arg) {
     return arg | -1;
   }
 
-  // CHECK-START: long Main.Rem0(long) constant_folding (before)
-  // CHECK-DAG:     <<Arg:j\d+>>           ParameterValue
-  // CHECK-DAG:     <<Const0:j\d+>>        LongConstant 0
-  // CHECK-DAG:     <<DivZeroCheck:j\d+>>  DivZeroCheck [<<Arg>>]
-  // CHECK-DAG:     <<Rem:j\d+>>           Rem [<<Const0>>,<<DivZeroCheck>>]
-  // CHECK-DAG:                            Return [<<Rem>>]
+  /// CHECK-START: long Main.Rem0(long) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>           ParameterValue
+  /// CHECK-DAG:     <<Const0:j\d+>>        LongConstant 0
+  /// CHECK-DAG:     <<DivZeroCheck:j\d+>>  DivZeroCheck [<<Arg>>]
+  /// CHECK-DAG:     <<Rem:j\d+>>           Rem [<<Const0>>,<<DivZeroCheck>>]
+  /// CHECK-DAG:                            Return [<<Rem>>]
 
-  // CHECK-START: long Main.Rem0(long) constant_folding (after)
-  // CHECK-DAG:     <<Const0:j\d+>>        LongConstant 0
-  // CHECK-NOT:                            Rem
-  // CHECK-DAG:                            Return [<<Const0>>]
+  /// CHECK-START: long Main.Rem0(long) constant_folding (after)
+  /// CHECK-DAG:     <<Const0:j\d+>>        LongConstant 0
+  /// CHECK-NOT:                            Rem
+  /// CHECK-DAG:                            Return [<<Const0>>]
 
   public static long Rem0(long arg) {
     return 0 % arg;
   }
 
-  // CHECK-START: int Main.Rem1(int) constant_folding (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<Rem:i\d+>>      Rem [<<Arg>>,<<Const1>>]
-  // CHECK-DAG:                       Return [<<Rem>>]
+  /// CHECK-START: int Main.Rem1(int) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<Rem:i\d+>>      Rem [<<Arg>>,<<Const1>>]
+  /// CHECK-DAG:                       Return [<<Rem>>]
 
-  // CHECK-START: int Main.Rem1(int) constant_folding (after)
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-NOT:                       Rem
-  // CHECK-DAG:                       Return [<<Const0>>]
+  /// CHECK-START: int Main.Rem1(int) constant_folding (after)
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-NOT:                       Rem
+  /// CHECK-DAG:                       Return [<<Const0>>]
 
   public static int Rem1(int arg) {
     return arg % 1;
   }
 
-  // CHECK-START: long Main.RemN1(long) constant_folding (before)
-  // CHECK-DAG:     <<Arg:j\d+>>           ParameterValue
-  // CHECK-DAG:     <<ConstN1:j\d+>>       LongConstant -1
-  // CHECK-DAG:     <<DivZeroCheck:j\d+>>  DivZeroCheck [<<ConstN1>>]
-  // CHECK-DAG:     <<Rem:j\d+>>           Rem [<<Arg>>,<<DivZeroCheck>>]
-  // CHECK-DAG:                            Return [<<Rem>>]
+  /// CHECK-START: long Main.RemN1(long) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>           ParameterValue
+  /// CHECK-DAG:     <<ConstN1:j\d+>>       LongConstant -1
+  /// CHECK-DAG:     <<DivZeroCheck:j\d+>>  DivZeroCheck [<<ConstN1>>]
+  /// CHECK-DAG:     <<Rem:j\d+>>           Rem [<<Arg>>,<<DivZeroCheck>>]
+  /// CHECK-DAG:                            Return [<<Rem>>]
 
-  // CHECK-START: long Main.RemN1(long) constant_folding (after)
-  // CHECK-DAG:     <<Const0:j\d+>>        LongConstant 0
-  // CHECK-NOT:                            Rem
-  // CHECK-DAG:                            Return [<<Const0>>]
+  /// CHECK-START: long Main.RemN1(long) constant_folding (after)
+  /// CHECK-DAG:     <<Const0:j\d+>>        LongConstant 0
+  /// CHECK-NOT:                            Rem
+  /// CHECK-DAG:                            Return [<<Const0>>]
 
   public static long RemN1(long arg) {
     return arg % -1;
   }
 
-  // CHECK-START: int Main.Shl0(int) constant_folding (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Shl:i\d+>>      Shl [<<Const0>>,<<Arg>>]
-  // CHECK-DAG:                       Return [<<Shl>>]
+  /// CHECK-START: int Main.Shl0(int) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Shl:i\d+>>      Shl [<<Const0>>,<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Shl>>]
 
-  // CHECK-START: int Main.Shl0(int) constant_folding (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-NOT:                       Shl
-  // CHECK-DAG:                       Return [<<Const0>>]
+  /// CHECK-START: int Main.Shl0(int) constant_folding (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-NOT:                       Shl
+  /// CHECK-DAG:                       Return [<<Const0>>]
 
   public static int Shl0(int arg) {
     return 0 << arg;
   }
 
-  // CHECK-START: long Main.Shr0(int) constant_folding (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
-  // CHECK-DAG:     <<Shr:j\d+>>      Shr [<<Const0>>,<<Arg>>]
-  // CHECK-DAG:                       Return [<<Shr>>]
+  /// CHECK-START: long Main.Shr0(int) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  /// CHECK-DAG:     <<Shr:j\d+>>      Shr [<<Const0>>,<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Shr>>]
 
-  // CHECK-START: long Main.Shr0(int) constant_folding (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
-  // CHECK-NOT:                       Shr
-  // CHECK-DAG:                       Return [<<Const0>>]
+  /// CHECK-START: long Main.Shr0(int) constant_folding (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  /// CHECK-NOT:                       Shr
+  /// CHECK-DAG:                       Return [<<Const0>>]
 
   public static long Shr0(int arg) {
     return (long)0 >> arg;
   }
 
-  // CHECK-START: long Main.SubSameLong(long) constant_folding (before)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Arg>>,<<Arg>>]
-  // CHECK-DAG:                       Return [<<Sub>>]
+  /// CHECK-START: long Main.SubSameLong(long) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Arg>>,<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Sub>>]
 
-  // CHECK-START: long Main.SubSameLong(long) constant_folding (after)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
-  // CHECK-NOT:                       Sub
-  // CHECK-DAG:                       Return [<<Const0>>]
+  /// CHECK-START: long Main.SubSameLong(long) constant_folding (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  /// CHECK-NOT:                       Sub
+  /// CHECK-DAG:                       Return [<<Const0>>]
 
   public static long SubSameLong(long arg) {
     return arg - arg;
   }
 
-  // CHECK-START: int Main.UShr0(int) constant_folding (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<UShr:i\d+>>     UShr [<<Const0>>,<<Arg>>]
-  // CHECK-DAG:                       Return [<<UShr>>]
+  /// CHECK-START: int Main.UShr0(int) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<UShr:i\d+>>     UShr [<<Const0>>,<<Arg>>]
+  /// CHECK-DAG:                       Return [<<UShr>>]
 
-  // CHECK-START: int Main.UShr0(int) constant_folding (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-NOT:                       UShr
-  // CHECK-DAG:                       Return [<<Const0>>]
+  /// CHECK-START: int Main.UShr0(int) constant_folding (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-NOT:                       UShr
+  /// CHECK-DAG:                       Return [<<Const0>>]
 
   public static int UShr0(int arg) {
     return 0 >>> arg;
   }
 
-  // CHECK-START: int Main.XorSameInt(int) constant_folding (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Xor:i\d+>>      Xor [<<Arg>>,<<Arg>>]
-  // CHECK-DAG:                       Return [<<Xor>>]
+  /// CHECK-START: int Main.XorSameInt(int) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Xor:i\d+>>      Xor [<<Arg>>,<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Xor>>]
 
-  // CHECK-START: int Main.XorSameInt(int) constant_folding (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-NOT:                       Xor
-  // CHECK-DAG:                       Return [<<Const0>>]
+  /// CHECK-START: int Main.XorSameInt(int) constant_folding (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-NOT:                       Xor
+  /// CHECK-DAG:                       Return [<<Const0>>]
 
   public static int XorSameInt(int arg) {
     return arg ^ arg;
   }
 
-  // CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (before)
-  // CHECK-DAG:     <<Arg:f\d+>>      ParameterValue
-  // CHECK-DAG:     <<ConstNan:f\d+>> FloatConstant nan
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:                       IntConstant 1
-  // CHECK-DAG:     <<Cmp:i\d+>>      Compare [<<Arg>>,<<ConstNan>>]
-  // CHECK-DAG:     <<Le:z\d+>>       LessThanOrEqual [<<Cmp>>,<<Const0>>]
-  // CHECK-DAG:                       If [<<Le>>]
+  /// CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:f\d+>>      ParameterValue
+  /// CHECK-DAG:     <<ConstNan:f\d+>> FloatConstant nan
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:                       IntConstant 1
+  /// CHECK-DAG:     <<Cmp:i\d+>>      Compare [<<Arg>>,<<ConstNan>>]
+  /// CHECK-DAG:     <<Le:z\d+>>       LessThanOrEqual [<<Cmp>>,<<Const0>>]
+  /// CHECK-DAG:                       If [<<Le>>]
 
-  // CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (after)
-  // CHECK-DAG:                       ParameterValue
-  // CHECK-DAG:                       FloatConstant nan
-  // CHECK-DAG:                       IntConstant 0
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:                       If [<<Const1>>]
+  /// CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (after)
+  /// CHECK-DAG:                       ParameterValue
+  /// CHECK-DAG:                       FloatConstant nan
+  /// CHECK-DAG:                       IntConstant 0
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:                       If [<<Const1>>]
 
-  // CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (after)
-  // CHECK-NOT:                       Compare
-  // CHECK-NOT:                       LessThanOrEqual
+  /// CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (after)
+  /// CHECK-NOT:                       Compare
+  /// CHECK-NOT:                       LessThanOrEqual
 
   public static boolean CmpFloatGreaterThanNaN(float arg) {
     return arg > Float.NaN;
   }
 
-  // CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (before)
-  // CHECK-DAG:     <<Arg:d\d+>>      ParameterValue
-  // CHECK-DAG:     <<ConstNan:d\d+>> DoubleConstant nan
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:                       IntConstant 1
-  // CHECK-DAG:     <<Cmp:i\d+>>      Compare [<<Arg>>,<<ConstNan>>]
-  // CHECK-DAG:     <<Ge:z\d+>>       GreaterThanOrEqual [<<Cmp>>,<<Const0>>]
-  // CHECK-DAG:                       If [<<Ge>>]
+  /// CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (before)
+  /// CHECK-DAG:     <<Arg:d\d+>>      ParameterValue
+  /// CHECK-DAG:     <<ConstNan:d\d+>> DoubleConstant nan
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:                       IntConstant 1
+  /// CHECK-DAG:     <<Cmp:i\d+>>      Compare [<<Arg>>,<<ConstNan>>]
+  /// CHECK-DAG:     <<Ge:z\d+>>       GreaterThanOrEqual [<<Cmp>>,<<Const0>>]
+  /// CHECK-DAG:                       If [<<Ge>>]
 
-  // CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (after)
-  // CHECK-DAG:                       ParameterValue
-  // CHECK-DAG:                       DoubleConstant nan
-  // CHECK-DAG:                       IntConstant 0
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:                       If [<<Const1>>]
+  /// CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (after)
+  /// CHECK-DAG:                       ParameterValue
+  /// CHECK-DAG:                       DoubleConstant nan
+  /// CHECK-DAG:                       IntConstant 0
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:                       If [<<Const1>>]
 
-  // CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (after)
-  // CHECK-NOT:                       Compare
-  // CHECK-NOT:                       GreaterThanOrEqual
+  /// CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (after)
+  /// CHECK-NOT:                       Compare
+  /// CHECK-NOT:                       GreaterThanOrEqual
 
   public static boolean CmpDoubleLessThanNaN(double arg) {
     return arg < Double.NaN;
   }
 
-  // CHECK-START: int Main.ReturnInt33() constant_folding (before)
-  // CHECK-DAG:     <<Const33:j\d+>>  LongConstant 33
-  // CHECK-DAG:     <<Convert:i\d+>>  TypeConversion [<<Const33>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: int Main.ReturnInt33() constant_folding (before)
+  /// CHECK-DAG:     <<Const33:j\d+>>  LongConstant 33
+  /// CHECK-DAG:     <<Convert:i\d+>>  TypeConversion [<<Const33>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: int Main.ReturnInt33() constant_folding (after)
-  // CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
-  // CHECK-DAG:                       Return [<<Const33>>]
+  /// CHECK-START: int Main.ReturnInt33() constant_folding (after)
+  /// CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
+  /// CHECK-DAG:                       Return [<<Const33>>]
 
   public static int ReturnInt33() {
     long imm = 33L;
     return (int) imm;
   }
 
-  // CHECK-START: int Main.ReturnIntMax() constant_folding (before)
-  // CHECK-DAG:     <<ConstMax:f\d+>> FloatConstant 1e+34
-  // CHECK-DAG:     <<Convert:i\d+>>  TypeConversion [<<ConstMax>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: int Main.ReturnIntMax() constant_folding (before)
+  /// CHECK-DAG:     <<ConstMax:f\d+>> FloatConstant 1e+34
+  /// CHECK-DAG:     <<Convert:i\d+>>  TypeConversion [<<ConstMax>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: int Main.ReturnIntMax() constant_folding (after)
-  // CHECK-DAG:     <<ConstMax:i\d+>> IntConstant 2147483647
-  // CHECK-DAG:                       Return [<<ConstMax>>]
+  /// CHECK-START: int Main.ReturnIntMax() constant_folding (after)
+  /// CHECK-DAG:     <<ConstMax:i\d+>> IntConstant 2147483647
+  /// CHECK-DAG:                       Return [<<ConstMax>>]
 
   public static int ReturnIntMax() {
     float imm = 1.0e34f;
     return (int) imm;
   }
 
-  // CHECK-START: int Main.ReturnInt0() constant_folding (before)
-  // CHECK-DAG:     <<ConstNaN:d\d+>> DoubleConstant nan
-  // CHECK-DAG:     <<Convert:i\d+>>  TypeConversion [<<ConstNaN>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: int Main.ReturnInt0() constant_folding (before)
+  /// CHECK-DAG:     <<ConstNaN:d\d+>> DoubleConstant nan
+  /// CHECK-DAG:     <<Convert:i\d+>>  TypeConversion [<<ConstNaN>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: int Main.ReturnInt0() constant_folding (after)
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:                       Return [<<Const0>>]
+  /// CHECK-START: int Main.ReturnInt0() constant_folding (after)
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:                       Return [<<Const0>>]
 
   public static int ReturnInt0() {
     double imm = Double.NaN;
     return (int) imm;
   }
 
-  // CHECK-START: long Main.ReturnLong33() constant_folding (before)
-  // CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
-  // CHECK-DAG:     <<Convert:j\d+>>  TypeConversion [<<Const33>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: long Main.ReturnLong33() constant_folding (before)
+  /// CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
+  /// CHECK-DAG:     <<Convert:j\d+>>  TypeConversion [<<Const33>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: long Main.ReturnLong33() constant_folding (after)
-  // CHECK-DAG:     <<Const33:j\d+>>  LongConstant 33
-  // CHECK-DAG:                       Return [<<Const33>>]
+  /// CHECK-START: long Main.ReturnLong33() constant_folding (after)
+  /// CHECK-DAG:     <<Const33:j\d+>>  LongConstant 33
+  /// CHECK-DAG:                       Return [<<Const33>>]
 
   public static long ReturnLong33() {
     int imm = 33;
     return (long) imm;
   }
 
-  // CHECK-START: long Main.ReturnLong34() constant_folding (before)
-  // CHECK-DAG:     <<Const34:f\d+>>  FloatConstant 34
-  // CHECK-DAG:     <<Convert:j\d+>>  TypeConversion [<<Const34>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: long Main.ReturnLong34() constant_folding (before)
+  /// CHECK-DAG:     <<Const34:f\d+>>  FloatConstant 34
+  /// CHECK-DAG:     <<Convert:j\d+>>  TypeConversion [<<Const34>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: long Main.ReturnLong34() constant_folding (after)
-  // CHECK-DAG:     <<Const34:j\d+>>  LongConstant 34
-  // CHECK-DAG:                       Return [<<Const34>>]
+  /// CHECK-START: long Main.ReturnLong34() constant_folding (after)
+  /// CHECK-DAG:     <<Const34:j\d+>>  LongConstant 34
+  /// CHECK-DAG:                       Return [<<Const34>>]
 
   public static long ReturnLong34() {
     float imm = 34.0f;
     return (long) imm;
   }
 
-  // CHECK-START: long Main.ReturnLong0() constant_folding (before)
-  // CHECK-DAG:     <<ConstNaN:d\d+>> DoubleConstant nan
-  // CHECK-DAG:     <<Convert:j\d+>>  TypeConversion [<<ConstNaN>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: long Main.ReturnLong0() constant_folding (before)
+  /// CHECK-DAG:     <<ConstNaN:d\d+>> DoubleConstant nan
+  /// CHECK-DAG:     <<Convert:j\d+>>  TypeConversion [<<ConstNaN>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: long Main.ReturnLong0() constant_folding (after)
-  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
-  // CHECK-DAG:                       Return [<<Const0>>]
+  /// CHECK-START: long Main.ReturnLong0() constant_folding (after)
+  /// CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  /// CHECK-DAG:                       Return [<<Const0>>]
 
   public static long ReturnLong0() {
     double imm = -Double.NaN;
     return (long) imm;
   }
 
-  // CHECK-START: float Main.ReturnFloat33() constant_folding (before)
-  // CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
-  // CHECK-DAG:     <<Convert:f\d+>>  TypeConversion [<<Const33>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: float Main.ReturnFloat33() constant_folding (before)
+  /// CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
+  /// CHECK-DAG:     <<Convert:f\d+>>  TypeConversion [<<Const33>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: float Main.ReturnFloat33() constant_folding (after)
-  // CHECK-DAG:     <<Const33:f\d+>>  FloatConstant 33
-  // CHECK-DAG:                       Return [<<Const33>>]
+  /// CHECK-START: float Main.ReturnFloat33() constant_folding (after)
+  /// CHECK-DAG:     <<Const33:f\d+>>  FloatConstant 33
+  /// CHECK-DAG:                       Return [<<Const33>>]
 
   public static float ReturnFloat33() {
     int imm = 33;
     return (float) imm;
   }
 
-  // CHECK-START: float Main.ReturnFloat34() constant_folding (before)
-  // CHECK-DAG:     <<Const34:j\d+>>  LongConstant 34
-  // CHECK-DAG:     <<Convert:f\d+>>  TypeConversion [<<Const34>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: float Main.ReturnFloat34() constant_folding (before)
+  /// CHECK-DAG:     <<Const34:j\d+>>  LongConstant 34
+  /// CHECK-DAG:     <<Convert:f\d+>>  TypeConversion [<<Const34>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: float Main.ReturnFloat34() constant_folding (after)
-  // CHECK-DAG:     <<Const34:f\d+>>  FloatConstant 34
-  // CHECK-DAG:                       Return [<<Const34>>]
+  /// CHECK-START: float Main.ReturnFloat34() constant_folding (after)
+  /// CHECK-DAG:     <<Const34:f\d+>>  FloatConstant 34
+  /// CHECK-DAG:                       Return [<<Const34>>]
 
   public static float ReturnFloat34() {
     long imm = 34L;
     return (float) imm;
   }
 
-  // CHECK-START: float Main.ReturnFloat99P25() constant_folding (before)
-  // CHECK-DAG:     <<Const:d\d+>>    DoubleConstant 99.25
-  // CHECK-DAG:     <<Convert:f\d+>>  TypeConversion [<<Const>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: float Main.ReturnFloat99P25() constant_folding (before)
+  /// CHECK-DAG:     <<Const:d\d+>>    DoubleConstant 99.25
+  /// CHECK-DAG:     <<Convert:f\d+>>  TypeConversion [<<Const>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: float Main.ReturnFloat99P25() constant_folding (after)
-  // CHECK-DAG:     <<Const:f\d+>>    FloatConstant 99.25
-  // CHECK-DAG:                       Return [<<Const>>]
+  /// CHECK-START: float Main.ReturnFloat99P25() constant_folding (after)
+  /// CHECK-DAG:     <<Const:f\d+>>    FloatConstant 99.25
+  /// CHECK-DAG:                       Return [<<Const>>]
 
   public static float ReturnFloat99P25() {
     double imm = 99.25;
     return (float) imm;
   }
 
-  // CHECK-START: double Main.ReturnDouble33() constant_folding (before)
-  // CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
-  // CHECK-DAG:     <<Convert:d\d+>>  TypeConversion [<<Const33>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: double Main.ReturnDouble33() constant_folding (before)
+  /// CHECK-DAG:     <<Const33:i\d+>>  IntConstant 33
+  /// CHECK-DAG:     <<Convert:d\d+>>  TypeConversion [<<Const33>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: double Main.ReturnDouble33() constant_folding (after)
-  // CHECK-DAG:     <<Const33:d\d+>>  DoubleConstant 33
-  // CHECK-DAG:                       Return [<<Const33>>]
+  /// CHECK-START: double Main.ReturnDouble33() constant_folding (after)
+  /// CHECK-DAG:     <<Const33:d\d+>>  DoubleConstant 33
+  /// CHECK-DAG:                       Return [<<Const33>>]
 
   public static double ReturnDouble33() {
     int imm = 33;
     return (double) imm;
   }
 
-  // CHECK-START: double Main.ReturnDouble34() constant_folding (before)
-  // CHECK-DAG:     <<Const34:j\d+>>  LongConstant 34
-  // CHECK-DAG:     <<Convert:d\d+>>  TypeConversion [<<Const34>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: double Main.ReturnDouble34() constant_folding (before)
+  /// CHECK-DAG:     <<Const34:j\d+>>  LongConstant 34
+  /// CHECK-DAG:     <<Convert:d\d+>>  TypeConversion [<<Const34>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: double Main.ReturnDouble34() constant_folding (after)
-  // CHECK-DAG:     <<Const34:d\d+>>  DoubleConstant 34
-  // CHECK-DAG:                       Return [<<Const34>>]
+  /// CHECK-START: double Main.ReturnDouble34() constant_folding (after)
+  /// CHECK-DAG:     <<Const34:d\d+>>  DoubleConstant 34
+  /// CHECK-DAG:                       Return [<<Const34>>]
 
   public static double ReturnDouble34() {
     long imm = 34L;
     return (double) imm;
   }
 
-  // CHECK-START: double Main.ReturnDouble99P25() constant_folding (before)
-  // CHECK-DAG:     <<Const:f\d+>>    FloatConstant 99.25
-  // CHECK-DAG:     <<Convert:d\d+>>  TypeConversion [<<Const>>]
-  // CHECK-DAG:                       Return [<<Convert>>]
+  /// CHECK-START: double Main.ReturnDouble99P25() constant_folding (before)
+  /// CHECK-DAG:     <<Const:f\d+>>    FloatConstant 99.25
+  /// CHECK-DAG:     <<Convert:d\d+>>  TypeConversion [<<Const>>]
+  /// CHECK-DAG:                       Return [<<Convert>>]
 
-  // CHECK-START: double Main.ReturnDouble99P25() constant_folding (after)
-  // CHECK-DAG:     <<Const:d\d+>>    DoubleConstant 99.25
-  // CHECK-DAG:                       Return [<<Const>>]
+  /// CHECK-START: double Main.ReturnDouble99P25() constant_folding (after)
+  /// CHECK-DAG:     <<Const:d\d+>>    DoubleConstant 99.25
+  /// CHECK-DAG:                       Return [<<Const>>]
 
   public static double ReturnDouble99P25() {
     float imm = 99.25f;
diff --git a/test/444-checker-nce/src/Main.java b/test/444-checker-nce/src/Main.java
index 501d79c..6ac0cad 100644
--- a/test/444-checker-nce/src/Main.java
+++ b/test/444-checker-nce/src/Main.java
@@ -16,63 +16,63 @@
 
 public class Main {
 
-  // CHECK-START: Main Main.keepTest(Main) instruction_simplifier_after_types (before)
-  // CHECK:         NullCheck
-  // CHECK:         InvokeStaticOrDirect
+  /// CHECK-START: Main Main.keepTest(Main) instruction_simplifier_after_types (before)
+  /// CHECK:         NullCheck
+  /// CHECK:         InvokeStaticOrDirect
 
-  // CHECK-START: Main Main.keepTest(Main) instruction_simplifier_after_types (after)
-  // CHECK:         NullCheck
-  // CHECK:         InvokeStaticOrDirect
+  /// CHECK-START: Main Main.keepTest(Main) instruction_simplifier_after_types (after)
+  /// CHECK:         NullCheck
+  /// CHECK:         InvokeStaticOrDirect
   public Main keepTest(Main m) {
     return m.g();
   }
 
-  // CHECK-START: Main Main.thisTest() instruction_simplifier (before)
-  // CHECK:         NullCheck
-  // CHECK:         InvokeStaticOrDirect
+  /// CHECK-START: Main Main.thisTest() instruction_simplifier (before)
+  /// CHECK:         NullCheck
+  /// CHECK:         InvokeStaticOrDirect
 
-  // CHECK-START: Main Main.thisTest() instruction_simplifier (after)
-  // CHECK-NOT:     NullCheck
-  // CHECK:         InvokeStaticOrDirect
+  /// CHECK-START: Main Main.thisTest() instruction_simplifier (after)
+  /// CHECK-NOT:     NullCheck
+  /// CHECK:         InvokeStaticOrDirect
   public Main thisTest() {
     return g();
   }
 
-  // CHECK-START: Main Main.newInstanceRemoveTest() instruction_simplifier (before)
-  // CHECK:         NewInstance
-  // CHECK:         NullCheck
-  // CHECK:         InvokeStaticOrDirect
-  // CHECK:         NullCheck
-  // CHECK:         InvokeStaticOrDirect
+  /// CHECK-START: Main Main.newInstanceRemoveTest() instruction_simplifier (before)
+  /// CHECK:         NewInstance
+  /// CHECK:         NullCheck
+  /// CHECK:         InvokeStaticOrDirect
+  /// CHECK:         NullCheck
+  /// CHECK:         InvokeStaticOrDirect
 
-  // CHECK-START: Main Main.newInstanceRemoveTest() instruction_simplifier (after)
-  // CHECK-NOT:     NullCheck
+  /// CHECK-START: Main Main.newInstanceRemoveTest() instruction_simplifier (after)
+  /// CHECK-NOT:     NullCheck
   public Main newInstanceRemoveTest() {
     Main m = new Main();
     return m.g();
   }
 
-  // CHECK-START: Main Main.newArrayRemoveTest() instruction_simplifier (before)
-  // CHECK:         NewArray
-  // CHECK:         NullCheck
-  // CHECK:         ArrayGet
+  /// CHECK-START: Main Main.newArrayRemoveTest() instruction_simplifier (before)
+  /// CHECK:         NewArray
+  /// CHECK:         NullCheck
+  /// CHECK:         ArrayGet
 
-  // CHECK-START: Main Main.newArrayRemoveTest() instruction_simplifier (after)
-  // CHECK:         NewArray
-  // CHECK-NOT:     NullCheck
-  // CHECK:         ArrayGet
+  /// CHECK-START: Main Main.newArrayRemoveTest() instruction_simplifier (after)
+  /// CHECK:         NewArray
+  /// CHECK-NOT:     NullCheck
+  /// CHECK:         ArrayGet
   public Main newArrayRemoveTest() {
     Main[] ms = new Main[1];
     return ms[0];
   }
 
-  // CHECK-START: Main Main.ifRemoveTest(boolean) instruction_simplifier_after_types (before)
-  // CHECK:         NewInstance
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.ifRemoveTest(boolean) instruction_simplifier_after_types (before)
+  /// CHECK:         NewInstance
+  /// CHECK:         NullCheck
 
-  // CHECK-START: Main Main.ifRemoveTest(boolean) instruction_simplifier_after_types (after)
-  // CHECK:         NewInstance
-  // CHECK-NOT:     NullCheck
+  /// CHECK-START: Main Main.ifRemoveTest(boolean) instruction_simplifier_after_types (after)
+  /// CHECK:         NewInstance
+  /// CHECK-NOT:     NullCheck
   public Main ifRemoveTest(boolean flag) {
     Main m = null;
     if (flag) {
@@ -83,13 +83,13 @@
     return m.g();
   }
 
-  // CHECK-START: Main Main.ifKeepTest(boolean) instruction_simplifier_after_types (before)
-  // CHECK:         NewInstance
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.ifKeepTest(boolean) instruction_simplifier_after_types (before)
+  /// CHECK:         NewInstance
+  /// CHECK:         NullCheck
 
-  // CHECK-START: Main Main.ifKeepTest(boolean) instruction_simplifier_after_types (after)
-  // CHECK:         NewInstance
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.ifKeepTest(boolean) instruction_simplifier_after_types (after)
+  /// CHECK:         NewInstance
+  /// CHECK:         NullCheck
   public Main ifKeepTest(boolean flag) {
     Main m = null;
     if (flag) {
@@ -98,11 +98,11 @@
     return m.g();
   }
 
-  // CHECK-START: Main Main.forRemoveTest(int) instruction_simplifier_after_types (before)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.forRemoveTest(int) instruction_simplifier_after_types (before)
+  /// CHECK:         NullCheck
 
-  // CHECK-START: Main Main.forRemoveTest(int) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     NullCheck
+  /// CHECK-START: Main Main.forRemoveTest(int) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     NullCheck
   public Main forRemoveTest(int count) {
     Main a = new Main();
     Main m = new Main();
@@ -114,11 +114,11 @@
     return m.g();
   }
 
-  // CHECK-START: Main Main.forKeepTest(int) instruction_simplifier_after_types (before)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.forKeepTest(int) instruction_simplifier_after_types (before)
+  /// CHECK:         NullCheck
 
-  // CHECK-START: Main Main.forKeepTest(int) instruction_simplifier_after_types (after)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.forKeepTest(int) instruction_simplifier_after_types (after)
+  /// CHECK:         NullCheck
   public Main forKeepTest(int count) {
     Main a = new Main();
     Main m = new Main();
@@ -132,11 +132,11 @@
     return m.g();
   }
 
-  // CHECK-START: Main Main.phiFlowRemoveTest(int) instruction_simplifier_after_types (before)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.phiFlowRemoveTest(int) instruction_simplifier_after_types (before)
+  /// CHECK:         NullCheck
 
-  // CHECK-START: Main Main.phiFlowRemoveTest(int) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     NullCheck
+  /// CHECK-START: Main Main.phiFlowRemoveTest(int) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     NullCheck
   public Main phiFlowRemoveTest(int count) {
     Main a = new Main();
     Main m = new Main();
@@ -154,11 +154,11 @@
     return n.g();
   }
 
-  // CHECK-START: Main Main.phiFlowKeepTest(int) instruction_simplifier_after_types (before)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.phiFlowKeepTest(int) instruction_simplifier_after_types (before)
+  /// CHECK:         NullCheck
 
-  // CHECK-START: Main Main.phiFlowKeepTest(int) instruction_simplifier_after_types (after)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.phiFlowKeepTest(int) instruction_simplifier_after_types (after)
+  /// CHECK:         NullCheck
   public Main phiFlowKeepTest(int count) {
     Main a = new Main();
     Main m = new Main();
@@ -178,11 +178,11 @@
     return n.g();
   }
 
-  // CHECK-START: Main Main.scopeRemoveTest(int, Main) instruction_simplifier (before)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.scopeRemoveTest(int, Main) instruction_simplifier (before)
+  /// CHECK:         NullCheck
 
-  // CHECK-START: Main Main.scopeRemoveTest(int, Main) instruction_simplifier (after)
-  // CHECK-NOT:     NullCheck
+  /// CHECK-START: Main Main.scopeRemoveTest(int, Main) instruction_simplifier (after)
+  /// CHECK-NOT:     NullCheck
   public Main scopeRemoveTest(int count, Main a) {
     Main m = null;
     for (int i = 0; i < count; i++) {
@@ -196,11 +196,11 @@
     return m;
   }
 
-  // CHECK-START: Main Main.scopeKeepTest(int, Main) instruction_simplifier_after_types (before)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.scopeKeepTest(int, Main) instruction_simplifier_after_types (before)
+  /// CHECK:         NullCheck
 
-  // CHECK-START: Main Main.scopeKeepTest(int, Main) instruction_simplifier_after_types (after)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.scopeKeepTest(int, Main) instruction_simplifier_after_types (after)
+  /// CHECK:         NullCheck
   public Main scopeKeepTest(int count, Main a) {
     Main m = new Main();
     for (int i = 0; i < count; i++) {
@@ -214,11 +214,11 @@
     return m;
   }
 
-  // CHECK-START: Main Main.scopeIfNotNullRemove(Main) instruction_simplifier_after_types (before)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.scopeIfNotNullRemove(Main) instruction_simplifier_after_types (before)
+  /// CHECK:         NullCheck
 
-  // CHECK-START: Main Main.scopeIfNotNullRemove(Main) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     NullCheck
+  /// CHECK-START: Main Main.scopeIfNotNullRemove(Main) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     NullCheck
   public Main scopeIfNotNullRemove(Main m) {
     if (m != null) {
       return m.g();
@@ -226,11 +226,11 @@
     return m;
   }
 
-  // CHECK-START: Main Main.scopeIfKeep(Main) instruction_simplifier_after_types (before)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.scopeIfKeep(Main) instruction_simplifier_after_types (before)
+  /// CHECK:         NullCheck
 
-  // CHECK-START: Main Main.scopeIfKeep(Main) instruction_simplifier_after_types (after)
-  // CHECK:         NullCheck
+  /// CHECK-START: Main Main.scopeIfKeep(Main) instruction_simplifier_after_types (after)
+  /// CHECK:         NullCheck
   public Main scopeIfKeep(Main m) {
     if (m == null) {
       m = new Main();
@@ -258,12 +258,12 @@
 class ListElement {
   private ListElement next;
 
-  // CHECK-START: boolean ListElement.isShorter(ListElement, ListElement) instruction_simplifier_after_types (before)
-  // CHECK:         NullCheck
-  // CHECK:         NullCheck
+  /// CHECK-START: boolean ListElement.isShorter(ListElement, ListElement) instruction_simplifier_after_types (before)
+  /// CHECK:         NullCheck
+  /// CHECK:         NullCheck
 
-  // CHECK-START: boolean ListElement.isShorter(ListElement, ListElement) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     NullCheck
+  /// CHECK-START: boolean ListElement.isShorter(ListElement, ListElement) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     NullCheck
   static boolean isShorter(ListElement x, ListElement y) {
     ListElement xTail = x;
     ListElement yTail = y;
diff --git a/test/445-checker-licm/src/Main.java b/test/445-checker-licm/src/Main.java
index 96918d3..42f9a11 100644
--- a/test/445-checker-licm/src/Main.java
+++ b/test/445-checker-licm/src/Main.java
@@ -16,14 +16,14 @@
 
 public class Main {
 
-  // CHECK-START: int Main.div() licm (before)
-  // CHECK-DAG: Div loop:{{B\d+}}
+  /// CHECK-START: int Main.div() licm (before)
+  /// CHECK-DAG: Div loop:{{B\d+}}
 
-  // CHECK-START: int Main.div() licm (after)
-  // CHECK-NOT: Div loop:{{B\d+}}
+  /// CHECK-START: int Main.div() licm (after)
+  /// CHECK-NOT: Div loop:{{B\d+}}
 
-  // CHECK-START: int Main.div() licm (after)
-  // CHECK-DAG: Div loop:none
+  /// CHECK-START: int Main.div() licm (after)
+  /// CHECK-DAG: Div loop:none
 
   public static int div() {
     int result = 0;
@@ -33,14 +33,14 @@
     return result;
   }
 
-  // CHECK-START: int Main.innerDiv() licm (before)
-  // CHECK-DAG: Div loop:{{B\d+}}
+  /// CHECK-START: int Main.innerDiv() licm (before)
+  /// CHECK-DAG: Div loop:{{B\d+}}
 
-  // CHECK-START: int Main.innerDiv() licm (after)
-  // CHECK-NOT: Div loop:{{B\d+}}
+  /// CHECK-START: int Main.innerDiv() licm (after)
+  /// CHECK-NOT: Div loop:{{B\d+}}
 
-  // CHECK-START: int Main.innerDiv() licm (after)
-  // CHECK-DAG: Div loop:none
+  /// CHECK-START: int Main.innerDiv() licm (after)
+  /// CHECK-DAG: Div loop:none
 
   public static int innerDiv() {
     int result = 0;
@@ -52,11 +52,11 @@
     return result;
   }
 
-  // CHECK-START: int Main.innerDiv2() licm (before)
-  // CHECK-DAG: Mul loop:B4
+  /// CHECK-START: int Main.innerDiv2() licm (before)
+  /// CHECK-DAG: Mul loop:B4
 
-  // CHECK-START: int Main.innerDiv2() licm (after)
-  // CHECK-DAG: Mul loop:B2
+  /// CHECK-START: int Main.innerDiv2() licm (after)
+  /// CHECK-DAG: Mul loop:B2
 
   public static int innerDiv2() {
     int result = 0;
@@ -71,11 +71,11 @@
     return result;
   }
 
-  // CHECK-START: int Main.innerDiv3(int, int) licm (before)
-  // CHECK-DAG: Div loop:{{B\d+}}
+  /// CHECK-START: int Main.innerDiv3(int, int) licm (before)
+  /// CHECK-DAG: Div loop:{{B\d+}}
 
-  // CHECK-START: int Main.innerDiv3(int, int) licm (after)
-  // CHECK-DAG: Div loop:{{B\d+}}
+  /// CHECK-START: int Main.innerDiv3(int, int) licm (after)
+  /// CHECK-DAG: Div loop:{{B\d+}}
 
   public static int innerDiv3(int a, int b) {
     int result = 0;
@@ -87,17 +87,17 @@
     return result;
   }
 
-  // CHECK-START: int Main.arrayLength(int[]) licm (before)
-  // CHECK-DAG: <<NullCheck:l\d+>> NullCheck loop:{{B\d+}}
-  // CHECK-DAG:                    ArrayLength [<<NullCheck>>] loop:{{B\d+}}
+  /// CHECK-START: int Main.arrayLength(int[]) licm (before)
+  /// CHECK-DAG: <<NullCheck:l\d+>> NullCheck loop:{{B\d+}}
+  /// CHECK-DAG:                    ArrayLength [<<NullCheck>>] loop:{{B\d+}}
 
-  // CHECK-START: int Main.arrayLength(int[]) licm (after)
-  // CHECK-NOT:                    NullCheck loop:{{B\d+}}
-  // CHECK-NOT:                    ArrayLength loop:{{B\d+}}
+  /// CHECK-START: int Main.arrayLength(int[]) licm (after)
+  /// CHECK-NOT:                    NullCheck loop:{{B\d+}}
+  /// CHECK-NOT:                    ArrayLength loop:{{B\d+}}
 
-  // CHECK-START: int Main.arrayLength(int[]) licm (after)
-  // CHECK-DAG: <<NullCheck:l\d+>> NullCheck loop:none
-  // CHECK-DAG:                    ArrayLength [<<NullCheck>>] loop:none
+  /// CHECK-START: int Main.arrayLength(int[]) licm (after)
+  /// CHECK-DAG: <<NullCheck:l\d+>> NullCheck loop:none
+  /// CHECK-DAG:                    ArrayLength [<<NullCheck>>] loop:none
 
   public static int arrayLength(int[] array) {
     int result = 0;
diff --git a/test/446-checker-inliner2/src/Main.java b/test/446-checker-inliner2/src/Main.java
index 9ed66d6..de00a09 100644
--- a/test/446-checker-inliner2/src/Main.java
+++ b/test/446-checker-inliner2/src/Main.java
@@ -16,16 +16,16 @@
 
 public class Main {
 
-  // CHECK-START: int Main.inlineInstanceCall(Main) inliner (before)
-  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: int Main.inlineInstanceCall(Main) inliner (before)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: int Main.inlineInstanceCall(Main) inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: int Main.inlineInstanceCall(Main) inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
-  // CHECK-START: int Main.inlineInstanceCall(Main) inliner (after)
-  // CHECK-DAG:     <<Field:i\d+>>   InstanceFieldGet
-  // CHECK-DAG:                      Return [<<Field>>]
+  /// CHECK-START: int Main.inlineInstanceCall(Main) inliner (after)
+  /// CHECK-DAG:     <<Field:i\d+>>   InstanceFieldGet
+  /// CHECK-DAG:                      Return [<<Field>>]
 
   public static int inlineInstanceCall(Main m) {
     return m.foo();
@@ -37,16 +37,16 @@
 
   int field = 42;
 
-  // CHECK-START: int Main.inlineNestedCall() inliner (before)
-  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: int Main.inlineNestedCall() inliner (before)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: int Main.inlineNestedCall() inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: int Main.inlineNestedCall() inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
-  // CHECK-START: int Main.inlineNestedCall() inliner (after)
-  // CHECK-DAG:     <<Const38:i\d+>> IntConstant 38
-  // CHECK-DAG:                      Return [<<Const38>>]
+  /// CHECK-START: int Main.inlineNestedCall() inliner (after)
+  /// CHECK-DAG:     <<Const38:i\d+>> IntConstant 38
+  /// CHECK-DAG:                      Return [<<Const38>>]
 
   public static int inlineNestedCall() {
     return nestedCall();
diff --git a/test/447-checker-inliner3/src/Main.java b/test/447-checker-inliner3/src/Main.java
index 9d022b9..e3fdffd 100644
--- a/test/447-checker-inliner3/src/Main.java
+++ b/test/447-checker-inliner3/src/Main.java
@@ -16,12 +16,12 @@
 
 public class Main {
 
-  // CHECK-START: int Main.inlineIfThenElse() inliner (before)
-  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: int Main.inlineIfThenElse() inliner (before)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: int Main.inlineIfThenElse() inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: int Main.inlineIfThenElse() inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
   public static int inlineIfThenElse() {
     return foo(true);
@@ -35,11 +35,11 @@
     }
   }
 
-  // CHECK-START: int Main.inlineInLoop() inliner (before)
-  // CHECK-DAG:     InvokeStaticOrDirect
+  /// CHECK-START: int Main.inlineInLoop() inliner (before)
+  /// CHECK-DAG:     InvokeStaticOrDirect
 
-  // CHECK-START: int Main.inlineInLoop() inliner (after)
-  // CHECK-NOT:     InvokeStaticOrDirect
+  /// CHECK-START: int Main.inlineInLoop() inliner (after)
+  /// CHECK-NOT:     InvokeStaticOrDirect
 
   public static int inlineInLoop() {
     int result = 0;
@@ -49,11 +49,11 @@
     return result;
   }
 
-  // CHECK-START: int Main.inlineInLoopHeader() inliner (before)
-  // CHECK-DAG:     InvokeStaticOrDirect
+  /// CHECK-START: int Main.inlineInLoopHeader() inliner (before)
+  /// CHECK-DAG:     InvokeStaticOrDirect
 
-  // CHECK-START: int Main.inlineInLoopHeader() inliner (after)
-  // CHECK-NOT:     InvokeStaticOrDirect
+  /// CHECK-START: int Main.inlineInLoopHeader() inliner (after)
+  /// CHECK-NOT:     InvokeStaticOrDirect
 
   public static int inlineInLoopHeader() {
     int result = 0;
diff --git a/test/449-checker-bce/src/Main.java b/test/449-checker-bce/src/Main.java
index f90d85d..8960df8 100644
--- a/test/449-checker-bce/src/Main.java
+++ b/test/449-checker-bce/src/Main.java
@@ -16,21 +16,21 @@
 
 public class Main {
 
-  // CHECK-START: int Main.sieve(int) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: int Main.sieve(int) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: int Main.sieve(int) BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: int Main.sieve(int) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
   static int sieve(int size) {
     int primeCount = 0;
@@ -47,25 +47,25 @@
   }
 
 
-  // CHECK-START: void Main.narrow(int[], int) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.narrow(int[], int) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.narrow(int[], int) BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.narrow(int[], int) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
   static void narrow(int[] array, int offset) {
     if (offset < 0) {
@@ -108,18 +108,18 @@
   }
 
 
-  // CHECK-START: void Main.constantIndexing1(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.constantIndexing1(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.constantIndexing1(int[]) BCE (after)
-  // CHECK-NOT: Deoptimize
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.constantIndexing1(int[]) BCE (after)
+  /// CHECK-NOT: Deoptimize
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
   static void constantIndexing1(int[] array) {
     array[5] = 1;
@@ -127,29 +127,29 @@
   }
 
 
-  // CHECK-START: void Main.constantIndexing2(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.constantIndexing2(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.constantIndexing2(int[]) BCE (after)
-  // CHECK: LessThanOrEqual
-  // CHECK: Deoptimize
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.constantIndexing2(int[]) BCE (after)
+  /// CHECK: LessThanOrEqual
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
   static void constantIndexing2(int[] array) {
     array[1] = 1;
@@ -160,45 +160,45 @@
   }
 
 
-  // CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (after)
-  // CHECK: LessThanOrEqual
-  // CHECK: Deoptimize
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: LessThanOrEqual
-  // CHECK: Deoptimize
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (after)
+  /// CHECK: LessThanOrEqual
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: LessThanOrEqual
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
   static int[] constantIndexing3(int[] array1, int[] array2, boolean copy) {
     if (!copy) {
@@ -212,14 +212,14 @@
   }
 
 
-  // CHECK-START: void Main.constantIndexing4(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.constantIndexing4(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.constantIndexing4(int[]) BCE (after)
-  // CHECK-NOT: LessThanOrEqual
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.constantIndexing4(int[]) BCE (after)
+  /// CHECK-NOT: LessThanOrEqual
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
   // There is only one array access. It's not beneficial
   // to create a compare with deoptimization instruction.
@@ -228,18 +228,18 @@
   }
 
 
-  // CHECK-START: void Main.constantIndexing5(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.constantIndexing5(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.constantIndexing5(int[]) BCE (after)
-  // CHECK-NOT: Deoptimize
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.constantIndexing5(int[]) BCE (after)
+  /// CHECK-NOT: Deoptimize
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
   static void constantIndexing5(int[] array) {
     // We don't apply the deoptimization for very large constant index
@@ -249,37 +249,37 @@
     array[Integer.MAX_VALUE - 998] = 1;
   }
 
-  // CHECK-START: void Main.loopPattern1(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.loopPattern1(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.loopPattern1(int[]) BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.loopPattern1(int[]) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
   static void loopPattern1(int[] array) {
     for (int i = 0; i < array.length; i++) {
@@ -316,33 +316,33 @@
   }
 
 
-  // CHECK-START: void Main.loopPattern2(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.loopPattern2(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.loopPattern2(int[]) BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.loopPattern2(int[]) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
   static void loopPattern2(int[] array) {
     for (int i = array.length - 1; i >= 0; i--) {
@@ -372,13 +372,13 @@
   }
 
 
-  // CHECK-START: void Main.loopPattern3(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.loopPattern3(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.loopPattern3(int[]) BCE (after)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.loopPattern3(int[]) BCE (after)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
   static void loopPattern3(int[] array) {
     java.util.Random random = new java.util.Random();
@@ -393,29 +393,29 @@
   }
 
 
-  // CHECK-START: void Main.constantNewArray() BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.constantNewArray() BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.constantNewArray() BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.constantNewArray() BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
   static void constantNewArray() {
     int[] array = new int[10];
@@ -437,13 +437,13 @@
     return 1;
   }
 
-  // CHECK-START: void Main.circularBufferProducer() BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.circularBufferProducer() BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.circularBufferProducer() BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.circularBufferProducer() BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
   static void circularBufferProducer() {
     byte[] array = new byte[4096];
@@ -455,17 +455,17 @@
   }
 
 
-  // CHECK-START: void Main.pyramid1(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.pyramid1(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.pyramid1(int[]) BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.pyramid1(int[]) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
   // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
   static void pyramid1(int[] array) {
@@ -476,17 +476,17 @@
   }
 
 
-  // CHECK-START: void Main.pyramid2(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.pyramid2(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.pyramid2(int[]) BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.pyramid2(int[]) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
   // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
   static void pyramid2(int[] array) {
@@ -497,17 +497,17 @@
   }
 
 
-  // CHECK-START: void Main.pyramid3(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.pyramid3(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.pyramid3(int[]) BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.pyramid3(int[]) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
   // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
   static void pyramid3(int[] array) {
@@ -518,17 +518,17 @@
   }
 
 
-  // CHECK-START: boolean Main.isPyramid(int[]) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: boolean Main.isPyramid(int[]) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
 
-  // CHECK-START: boolean Main.isPyramid(int[]) BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: boolean Main.isPyramid(int[]) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
   static boolean isPyramid(int[] array) {
     int i = 0;
@@ -546,43 +546,43 @@
   }
 
 
-  // CHECK-START: void Main.bubbleSort(int[]) GVN (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.bubbleSort(int[]) GVN (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.bubbleSort(int[]) GVN (after)
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: ArrayGet
-  // CHECK-NOT: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.bubbleSort(int[]) GVN (after)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: ArrayGet
+  /// CHECK-NOT: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.bubbleSort(int[]) BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: ArrayGet
-  // CHECK-NOT: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.bubbleSort(int[]) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: ArrayGet
+  /// CHECK-NOT: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
   static void bubbleSort(int[] array) {
     for (int i = 0; i < array.length - 1; i++) {
@@ -610,22 +610,22 @@
 
   int sum;
 
-  // CHECK-START: void Main.foo1(int[], int, int) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo1(int[], int, int) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
-  // CHECK-START: void Main.foo1(int[], int, int) BCE (after)
-  // CHECK: Deoptimize
-  // CHECK: Deoptimize
-  // CHECK: Deoptimize
-  // CHECK-NOT: Deoptimize
-  // CHECK: Phi
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo1(int[], int, int) BCE (after)
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: Deoptimize
+  /// CHECK: Phi
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
   void foo1(int[] array, int start, int end) {
     // Three HDeoptimize will be added. One for
@@ -639,22 +639,22 @@
   }
 
 
-  // CHECK-START: void Main.foo2(int[], int, int) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo2(int[], int, int) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
-  // CHECK-START: void Main.foo2(int[], int, int) BCE (after)
-  // CHECK: Deoptimize
-  // CHECK: Deoptimize
-  // CHECK: Deoptimize
-  // CHECK-NOT: Deoptimize
-  // CHECK: Phi
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo2(int[], int, int) BCE (after)
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: Deoptimize
+  /// CHECK: Phi
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
   void foo2(int[] array, int start, int end) {
     // Three HDeoptimize will be added. One for
@@ -668,21 +668,21 @@
   }
 
 
-  // CHECK-START: void Main.foo3(int[], int) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo3(int[], int) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
-  // CHECK-START: void Main.foo3(int[], int) BCE (after)
-  // CHECK: Deoptimize
-  // CHECK: Deoptimize
-  // CHECK-NOT: Deoptimize
-  // CHECK: Phi
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo3(int[], int) BCE (after)
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: Deoptimize
+  /// CHECK: Phi
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
   void foo3(int[] array, int end) {
     // Two HDeoptimize will be added. One for end < array.length,
@@ -694,21 +694,21 @@
     }
   }
 
-  // CHECK-START: void Main.foo4(int[], int) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo4(int[], int) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
-  // CHECK-START: void Main.foo4(int[], int) BCE (after)
-  // CHECK: Deoptimize
-  // CHECK: Deoptimize
-  // CHECK-NOT: Deoptimize
-  // CHECK: Phi
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo4(int[], int) BCE (after)
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: Deoptimize
+  /// CHECK: Phi
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
   void foo4(int[] array, int end) {
     // Two HDeoptimize will be added. One for end <= array.length,
@@ -721,28 +721,28 @@
   }
 
 
-  // CHECK-START: void Main.foo5(int[], int) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo5(int[], int) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
 
-  // CHECK-START: void Main.foo5(int[], int) BCE (after)
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
-  // CHECK: Deoptimize
-  // CHECK-NOT: Deoptimize
-  // CHECK: Phi
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo5(int[], int) BCE (after)
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: Deoptimize
+  /// CHECK: Phi
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
   void foo5(int[] array, int end) {
     // Bounds check in this loop can be eliminated without deoptimization.
@@ -759,38 +759,38 @@
   }
 
 
-  // CHECK-START: void Main.foo6(int[], int, int) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.foo6(int[], int, int) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.foo6(int[], int, int) BCE (after)
-  // CHECK: Deoptimize
-  // CHECK: Deoptimize
-  // CHECK: Deoptimize
-  // CHECK-NOT: Deoptimize
-  // CHECK: Phi
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.foo6(int[], int, int) BCE (after)
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: Deoptimize
+  /// CHECK: Phi
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArraySet
 
   void foo6(int[] array, int start, int end) {
     // Three HDeoptimize will be added. One for
@@ -803,22 +803,22 @@
   }
 
 
-  // CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
 
-  // CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after)
-  // CHECK: Deoptimize
-  // CHECK: Deoptimize
-  // CHECK: Deoptimize
-  // CHECK-NOT: Deoptimize
-  // CHECK: Phi
-  // CHECK: BoundsCheck
-  // CHECK: ArrayGet
-  // CHECK-NOT: BoundsCheck
-  // CHECK: ArrayGet
+  /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after)
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK: Deoptimize
+  /// CHECK-NOT: Deoptimize
+  /// CHECK: Phi
+  /// CHECK: BoundsCheck
+  /// CHECK: ArrayGet
+  /// CHECK-NOT: BoundsCheck
+  /// CHECK: ArrayGet
 
   void foo7(int[] array, int start, int end, boolean lowEnd) {
     // Three HDeoptimize will be added. One for
@@ -837,14 +837,14 @@
   }
 
 
-  // CHECK-START: void Main.partialLooping(int[], int, int) BCE (before)
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before)
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
-  // CHECK-START: void Main.partialLooping(int[], int, int) BCE (after)
-  // CHECK-NOT: Deoptimize
-  // CHECK: BoundsCheck
-  // CHECK: ArraySet
+  /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after)
+  /// CHECK-NOT: Deoptimize
+  /// CHECK: BoundsCheck
+  /// CHECK: ArraySet
 
   void partialLooping(int[] array, int start, int end) {
     // This loop doesn't cover the full range of [start, end) so
@@ -983,8 +983,8 @@
   }
 
   // Make sure this method is compiled with optimizing.
-  // CHECK-START: void Main.main(java.lang.String[]) register (after)
-  // CHECK: ParallelMove
+  /// CHECK-START: void Main.main(java.lang.String[]) register (after)
+  /// CHECK: ParallelMove
 
   public static void main(String[] args) {
     sieve(20);
diff --git a/test/450-checker-types/src/Main.java b/test/450-checker-types/src/Main.java
index 640aeb8..9bf7cdf 100644
--- a/test/450-checker-types/src/Main.java
+++ b/test/450-checker-types/src/Main.java
@@ -54,50 +54,50 @@
 
 public class Main {
 
-  // CHECK-START: void Main.testSimpleRemove() instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testSimpleRemove() instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testSimpleRemove() instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testSimpleRemove() instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testSimpleRemove() {
     Super s = new SubclassA();
     ((SubclassA)s).g();
   }
 
-  // CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier_after_types (after)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier_after_types (after)
+  /// CHECK:         CheckCast
   public void testSimpleKeep(Super s) {
     ((SubclassA)s).f();
   }
 
-  // CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public String testClassRemove() {
     Object s = SubclassA.class;
     return ((Class)s).getName();
   }
 
-  // CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier_after_types (after)
-  // CHECK:         CheckCast
+  /// CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier_after_types (after)
+  /// CHECK:         CheckCast
   public String testClassKeep() {
     Object s = SubclassA.class;
     return ((SubclassA)s).h();
   }
 
-  // CHECK-START: void Main.testIfRemove(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testIfRemove(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testIfRemove(int) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testIfRemove(int) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testIfRemove(int x) {
     Super s;
     if (x % 2 == 0) {
@@ -108,11 +108,11 @@
     ((SubclassA)s).g();
   }
 
-  // CHECK-START: void Main.testIfKeep(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testIfKeep(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testIfKeep(int) instruction_simplifier_after_types (after)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testIfKeep(int) instruction_simplifier_after_types (after)
+  /// CHECK:         CheckCast
   public void testIfKeep(int x) {
     Super s;
     if (x % 2 == 0) {
@@ -123,11 +123,11 @@
     ((SubclassA)s).g();
   }
 
-  // CHECK-START: void Main.testForRemove(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testForRemove(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testForRemove(int) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testForRemove(int) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testForRemove(int x) {
     Super s = new SubclassA();
     for (int i = 0 ; i < x; i++) {
@@ -138,11 +138,11 @@
     ((SubclassA)s).g();
   }
 
-  // CHECK-START: void Main.testForKeep(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testForKeep(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testForKeep(int) instruction_simplifier_after_types (after)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testForKeep(int) instruction_simplifier_after_types (after)
+  /// CHECK:         CheckCast
   public void testForKeep(int x) {
     Super s = new SubclassA();
     for (int i = 0 ; i < x; i++) {
@@ -153,11 +153,11 @@
     ((SubclassC)s).g();
   }
 
-  // CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier_after_types (after)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier_after_types (after)
+  /// CHECK:         CheckCast
   public void testPhiFromCall(int i) {
     Object x;
     if (i % 2 == 0) {
@@ -168,12 +168,12 @@
     ((SubclassC)x).g();
   }
 
-  // CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testInstanceOf(Object o) {
     if (o instanceof SubclassC) {
       ((SubclassC)o).g();
@@ -183,13 +183,13 @@
     }
   }
 
-  // CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier_after_types (after)
-  // CHECK:         CheckCast
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier_after_types (after)
+  /// CHECK:         CheckCast
+  /// CHECK:         CheckCast
   public void testInstanceOfKeep(Object o) {
     if (o instanceof SubclassC) {
       ((SubclassB)o).g();
@@ -199,12 +199,12 @@
     }
   }
 
-  // CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testInstanceOfNested(Object o) {
     if (o instanceof SubclassC) {
       if (o instanceof SubclassB) {
@@ -215,11 +215,11 @@
     }
   }
 
-  // CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testInstanceOfWithPhi(int i) {
     Object o;
     if (i == 0) {
@@ -233,11 +233,11 @@
     }
   }
 
-  // CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testInstanceOfInFor(int n) {
     Object o = new SubclassA();
     for (int i = 0; i < n; i++) {
@@ -250,11 +250,11 @@
     }
   }
 
-  // CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testInstanceOfSubclass() {
     Object o = new SubclassA();
     if (o instanceof Super) {
@@ -262,11 +262,11 @@
     }
   }
 
-  // CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testInstanceOfWithPhiSubclass(int i) {
     Object o;
     if (i == 0) {
@@ -280,11 +280,11 @@
     }
   }
 
-  // CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testInstanceOfWithPhiTop(int i) {
     Object o;
     if (i == 0) {
@@ -298,11 +298,11 @@
     }
   }
 
-  // CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testInstanceOfSubclassInFor(int n) {
     Object o = new SubclassA();
     for (int i = 0; i < n; i++) {
@@ -315,11 +315,11 @@
     }
   }
 
-  // CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier_after_types (before)
-  // CHECK:         CheckCast
+  /// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
 
-  // CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier_after_types (after)
-  // CHECK-NOT:     CheckCast
+  /// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
   public void testInstanceOfTopInFor(int n) {
     Object o = new SubclassA();
     for (int i = 0; i < n; i++) {
@@ -340,6 +340,30 @@
     }
   }
 
+  public SubclassA a = new SubclassA();
+  public static SubclassA b = new SubclassA();
+
+  /// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
+
+  /// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
+  public void testInstanceFieldGetSimpleRemove() {
+    Main m = new Main();
+    Super a = m.a;
+    ((SubclassA)a).g();
+  }
+
+  /// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier_after_types (before)
+  /// CHECK:         CheckCast
+
+  /// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier_after_types (after)
+  /// CHECK-NOT:     CheckCast
+  public void testStaticFieldGetSimpleRemove() {
+    Super b = Main.b;
+    ((SubclassA)b).g();
+  }
+
   public static void main(String[] args) {
   }
 }
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-checker-gvn/src/Main.java b/test/455-checker-gvn/src/Main.java
index e94fc46..9824f27 100644
--- a/test/455-checker-gvn/src/Main.java
+++ b/test/455-checker-gvn/src/Main.java
@@ -19,15 +19,15 @@
     System.out.println(foo(3, 4));
   }
 
-  // CHECK-START: int Main.foo(int, int) GVN (before)
-  // CHECK: Add
-  // CHECK: Add
-  // CHECK: Add
+  /// CHECK-START: int Main.foo(int, int) GVN (before)
+  /// CHECK: Add
+  /// CHECK: Add
+  /// CHECK: Add
 
-  // CHECK-START: int Main.foo(int, int) GVN (after)
-  // CHECK: Add
-  // CHECK: Add
-  // CHECK-NOT: Add
+  /// CHECK-START: int Main.foo(int, int) GVN (after)
+  /// CHECK: Add
+  /// CHECK: Add
+  /// CHECK-NOT: Add
 
   public static int foo(int x, int y) {
     int sum1 = x + y;
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/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index 742210c..ad5fc8e 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -50,296 +50,296 @@
    * Tiny programs exercising optimizations of arithmetic identities.
    */
 
-  // CHECK-START: long Main.Add0(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Const0:j\d+>>  LongConstant 0
-  // CHECK-DAG:     <<Add:j\d+>>     Add [<<Const0>>,<<Arg>>]
-  // CHECK-DAG:                      Return [<<Add>>]
+  /// CHECK-START: long Main.Add0(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Const0:j\d+>>  LongConstant 0
+  /// CHECK-DAG:     <<Add:j\d+>>     Add [<<Const0>>,<<Arg>>]
+  /// CHECK-DAG:                      Return [<<Add>>]
 
-  // CHECK-START: long Main.Add0(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
-  // CHECK-DAG:                      Return [<<Arg>>]
+  /// CHECK-START: long Main.Add0(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  /// CHECK-DAG:                      Return [<<Arg>>]
 
-  // CHECK-START: long Main.Add0(long) instruction_simplifier (after)
-  // CHECK-NOT:                        Add
+  /// CHECK-START: long Main.Add0(long) instruction_simplifier (after)
+  /// CHECK-NOT:                        Add
 
   public static long Add0(long arg) {
     return 0 + arg;
   }
 
-  // CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<ConstF:i\d+>>  IntConstant -1
-  // CHECK-DAG:     <<And:i\d+>>     And [<<Arg>>,<<ConstF>>]
-  // CHECK-DAG:                      Return [<<And>>]
+  /// CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<ConstF:i\d+>>  IntConstant -1
+  /// CHECK-DAG:     <<And:i\d+>>     And [<<Arg>>,<<ConstF>>]
+  /// CHECK-DAG:                      Return [<<And>>]
 
-  // CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
-  // CHECK-DAG:                      Return [<<Arg>>]
+  /// CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
+  /// CHECK-DAG:                      Return [<<Arg>>]
 
-  // CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after)
-  // CHECK-NOT:                      And
+  /// CHECK-START: int Main.AndAllOnes(int) instruction_simplifier (after)
+  /// CHECK-NOT:                      And
 
   public static int AndAllOnes(int arg) {
     return arg & -1;
   }
 
-  // CHECK-START: long Main.Div1(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Const1:j\d+>>  LongConstant 1
-  // CHECK-DAG:     <<Div:j\d+>>     Div [<<Arg>>,<<Const1>>]
-  // CHECK-DAG:                      Return [<<Div>>]
+  /// CHECK-START: long Main.Div1(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Const1:j\d+>>  LongConstant 1
+  /// CHECK-DAG:     <<Div:j\d+>>     Div [<<Arg>>,<<Const1>>]
+  /// CHECK-DAG:                      Return [<<Div>>]
 
-  // CHECK-START: long Main.Div1(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
-  // CHECK-DAG:                      Return [<<Arg>>]
+  /// CHECK-START: long Main.Div1(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  /// CHECK-DAG:                      Return [<<Arg>>]
 
-  // CHECK-START: long Main.Div1(long) instruction_simplifier (after)
-  // CHECK-NOT:                      Div
+  /// CHECK-START: long Main.Div1(long) instruction_simplifier (after)
+  /// CHECK-NOT:                      Div
 
   public static long Div1(long arg) {
     return arg / 1;
   }
 
-  // CHECK-START: int Main.DivN1(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<ConstN1:i\d+>>  IntConstant -1
-  // CHECK-DAG:     <<Div:i\d+>>      Div [<<Arg>>,<<ConstN1>>]
-  // CHECK-DAG:                       Return [<<Div>>]
+  /// CHECK-START: int Main.DivN1(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<ConstN1:i\d+>>  IntConstant -1
+  /// CHECK-DAG:     <<Div:i\d+>>      Div [<<Arg>>,<<ConstN1>>]
+  /// CHECK-DAG:                       Return [<<Div>>]
 
-  // CHECK-START: int Main.DivN1(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg>>]
-  // CHECK-DAG:                       Return [<<Neg>>]
+  /// CHECK-START: int Main.DivN1(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Neg>>]
 
-  // CHECK-START: int Main.DivN1(int) instruction_simplifier (after)
-  // CHECK-NOT:                       Div
+  /// CHECK-START: int Main.DivN1(int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Div
 
   public static int DivN1(int arg) {
     return arg / -1;
   }
 
-  // CHECK-START: long Main.Mul1(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Const1:j\d+>>  LongConstant 1
-  // CHECK-DAG:     <<Mul:j\d+>>     Mul [<<Arg>>,<<Const1>>]
-  // CHECK-DAG:                      Return [<<Mul>>]
+  /// CHECK-START: long Main.Mul1(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Const1:j\d+>>  LongConstant 1
+  /// CHECK-DAG:     <<Mul:j\d+>>     Mul [<<Arg>>,<<Const1>>]
+  /// CHECK-DAG:                      Return [<<Mul>>]
 
-  // CHECK-START: long Main.Mul1(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
-  // CHECK-DAG:                      Return [<<Arg>>]
+  /// CHECK-START: long Main.Mul1(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>     ParameterValue
+  /// CHECK-DAG:                      Return [<<Arg>>]
 
-  // CHECK-START: long Main.Mul1(long) instruction_simplifier (after)
-  // CHECK-NOT:                       Mul
+  /// CHECK-START: long Main.Mul1(long) instruction_simplifier (after)
+  /// CHECK-NOT:                       Mul
 
   public static long Mul1(long arg) {
     return arg * 1;
   }
 
-  // CHECK-START: int Main.MulN1(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<ConstN1:i\d+>>  IntConstant -1
-  // CHECK-DAG:     <<Mul:i\d+>>      Mul [<<Arg>>,<<ConstN1>>]
-  // CHECK-DAG:                       Return [<<Mul>>]
+  /// CHECK-START: int Main.MulN1(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<ConstN1:i\d+>>  IntConstant -1
+  /// CHECK-DAG:     <<Mul:i\d+>>      Mul [<<Arg>>,<<ConstN1>>]
+  /// CHECK-DAG:                       Return [<<Mul>>]
 
-  // CHECK-START: int Main.MulN1(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg>>]
-  // CHECK-DAG:                       Return [<<Neg>>]
+  /// CHECK-START: int Main.MulN1(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Neg>>]
 
-  // CHECK-START: int Main.MulN1(int) instruction_simplifier (after)
-  // CHECK-NOT:                       Mul
+  /// CHECK-START: int Main.MulN1(int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Mul
 
   public static int MulN1(int arg) {
     return arg * -1;
   }
 
-  // CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
-  // CHECK-DAG:     <<Const128:j\d+>>  LongConstant 128
-  // CHECK-DAG:     <<Mul:j\d+>>       Mul [<<Arg>>,<<Const128>>]
-  // CHECK-DAG:                        Return [<<Mul>>]
+  /// CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
+  /// CHECK-DAG:     <<Const128:j\d+>>  LongConstant 128
+  /// CHECK-DAG:     <<Mul:j\d+>>       Mul [<<Arg>>,<<Const128>>]
+  /// CHECK-DAG:                        Return [<<Mul>>]
 
-  // CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
-  // CHECK-DAG:     <<Const7:i\d+>>    IntConstant 7
-  // CHECK-DAG:     <<Shl:j\d+>>       Shl [<<Arg>>,<<Const7>>]
-  // CHECK-DAG:                        Return [<<Shl>>]
+  /// CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
+  /// CHECK-DAG:     <<Const7:i\d+>>    IntConstant 7
+  /// CHECK-DAG:     <<Shl:j\d+>>       Shl [<<Arg>>,<<Const7>>]
+  /// CHECK-DAG:                        Return [<<Shl>>]
 
-  // CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after)
-  // CHECK-NOT:                        Mul
+  /// CHECK-START: long Main.MulPowerOfTwo128(long) instruction_simplifier (after)
+  /// CHECK-NOT:                        Mul
 
   public static long MulPowerOfTwo128(long arg) {
     return arg * 128;
   }
 
-  // CHECK-START: int Main.Or0(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Arg>>,<<Const0>>]
-  // CHECK-DAG:                       Return [<<Or>>]
+  /// CHECK-START: int Main.Or0(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Or:i\d+>>       Or [<<Arg>>,<<Const0>>]
+  /// CHECK-DAG:                       Return [<<Or>>]
 
-  // CHECK-START: int Main.Or0(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:                       Return [<<Arg>>]
+  /// CHECK-START: int Main.Or0(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:                       Return [<<Arg>>]
 
-  // CHECK-START: int Main.Or0(int) instruction_simplifier (after)
-  // CHECK-NOT:                       Or
+  /// CHECK-START: int Main.Or0(int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Or
 
   public static int Or0(int arg) {
     return arg | 0;
   }
 
-  // CHECK-START: long Main.OrSame(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
-  // CHECK-DAG:     <<Or:j\d+>>        Or [<<Arg>>,<<Arg>>]
-  // CHECK-DAG:                        Return [<<Or>>]
+  /// CHECK-START: long Main.OrSame(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
+  /// CHECK-DAG:     <<Or:j\d+>>        Or [<<Arg>>,<<Arg>>]
+  /// CHECK-DAG:                        Return [<<Or>>]
 
-  // CHECK-START: long Main.OrSame(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
-  // CHECK-DAG:                        Return [<<Arg>>]
+  /// CHECK-START: long Main.OrSame(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>       ParameterValue
+  /// CHECK-DAG:                        Return [<<Arg>>]
 
-  // CHECK-START: long Main.OrSame(long) instruction_simplifier (after)
-  // CHECK-NOT:                        Or
+  /// CHECK-START: long Main.OrSame(long) instruction_simplifier (after)
+  /// CHECK-NOT:                        Or
 
   public static long OrSame(long arg) {
     return arg | arg;
   }
 
-  // CHECK-START: int Main.Shl0(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Shl:i\d+>>      Shl [<<Arg>>,<<Const0>>]
-  // CHECK-DAG:                       Return [<<Shl>>]
+  /// CHECK-START: int Main.Shl0(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Shl:i\d+>>      Shl [<<Arg>>,<<Const0>>]
+  /// CHECK-DAG:                       Return [<<Shl>>]
 
-  // CHECK-START: int Main.Shl0(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:                       Return [<<Arg>>]
+  /// CHECK-START: int Main.Shl0(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:                       Return [<<Arg>>]
 
-  // CHECK-START: int Main.Shl0(int) instruction_simplifier (after)
-  // CHECK-NOT:                       Shl
+  /// CHECK-START: int Main.Shl0(int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Shl
 
   public static int Shl0(int arg) {
     return arg << 0;
   }
 
-  // CHECK-START: int Main.Shl1(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<Shl:i\d+>>      Shl [<<Arg>>,<<Const1>>]
-  // CHECK-DAG:                       Return [<<Shl>>]
+  /// CHECK-START: int Main.Shl1(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<Shl:i\d+>>      Shl [<<Arg>>,<<Const1>>]
+  /// CHECK-DAG:                       Return [<<Shl>>]
 
-  // CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Arg>>,<<Arg>>]
-  // CHECK-DAG:                       Return [<<Add>>]
+  /// CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Add:i\d+>>      Add [<<Arg>>,<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Add>>]
 
-  // CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
-  // CHECK-NOT:                       Shl
+  /// CHECK-START: int Main.Shl1(int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Shl
 
   public static int Shl1(int arg) {
     return arg << 1;
   }
 
-  // CHECK-START: long Main.Shr0(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Shr:j\d+>>      Shr [<<Arg>>,<<Const0>>]
-  // CHECK-DAG:                       Return [<<Shr>>]
+  /// CHECK-START: long Main.Shr0(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Shr:j\d+>>      Shr [<<Arg>>,<<Const0>>]
+  /// CHECK-DAG:                       Return [<<Shr>>]
 
-  // CHECK-START: long Main.Shr0(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:                       Return [<<Arg>>]
+  /// CHECK-START: long Main.Shr0(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:                       Return [<<Arg>>]
 
-  // CHECK-START: long Main.Shr0(long) instruction_simplifier (after)
-  // CHECK-NOT:                       Shr
+  /// CHECK-START: long Main.Shr0(long) instruction_simplifier (after)
+  /// CHECK-NOT:                       Shr
 
   public static long Shr0(long arg) {
     return arg >> 0;
   }
 
-  // CHECK-START: long Main.Sub0(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
-  // CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Arg>>,<<Const0>>]
-  // CHECK-DAG:                       Return [<<Sub>>]
+  /// CHECK-START: long Main.Sub0(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  /// CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Arg>>,<<Const0>>]
+  /// CHECK-DAG:                       Return [<<Sub>>]
 
-  // CHECK-START: long Main.Sub0(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:                       Return [<<Arg>>]
+  /// CHECK-START: long Main.Sub0(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:                       Return [<<Arg>>]
 
-  // CHECK-START: long Main.Sub0(long) instruction_simplifier (after)
-  // CHECK-NOT:                       Sub
+  /// CHECK-START: long Main.Sub0(long) instruction_simplifier (after)
+  /// CHECK-NOT:                       Sub
 
   public static long Sub0(long arg) {
     return arg - 0;
   }
 
-  // CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Const0>>,<<Arg>>]
-  // CHECK-DAG:                       Return [<<Sub>>]
+  /// CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Const0>>,<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Sub>>]
 
-  // CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg>>]
-  // CHECK-DAG:                       Return [<<Neg>>]
+  /// CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Neg>>]
 
-  // CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after)
-  // CHECK-NOT:                       Sub
+  /// CHECK-START: int Main.SubAliasNeg(int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Sub
 
   public static int SubAliasNeg(int arg) {
     return 0 - arg;
   }
 
-  // CHECK-START: long Main.UShr0(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<UShr:j\d+>>     UShr [<<Arg>>,<<Const0>>]
-  // CHECK-DAG:                       Return [<<UShr>>]
+  /// CHECK-START: long Main.UShr0(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<UShr:j\d+>>     UShr [<<Arg>>,<<Const0>>]
+  /// CHECK-DAG:                       Return [<<UShr>>]
 
-  // CHECK-START: long Main.UShr0(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:                       Return [<<Arg>>]
+  /// CHECK-START: long Main.UShr0(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:                       Return [<<Arg>>]
 
-  // CHECK-START: long Main.UShr0(long) instruction_simplifier (after)
-  // CHECK-NOT:                       UShr
+  /// CHECK-START: long Main.UShr0(long) instruction_simplifier (after)
+  /// CHECK-NOT:                       UShr
 
   public static long UShr0(long arg) {
     return arg >>> 0;
   }
 
-  // CHECK-START: int Main.Xor0(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Xor:i\d+>>      Xor [<<Arg>>,<<Const0>>]
-  // CHECK-DAG:                       Return [<<Xor>>]
+  /// CHECK-START: int Main.Xor0(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Xor:i\d+>>      Xor [<<Arg>>,<<Const0>>]
+  /// CHECK-DAG:                       Return [<<Xor>>]
 
-  // CHECK-START: int Main.Xor0(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:                       Return [<<Arg>>]
+  /// CHECK-START: int Main.Xor0(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:                       Return [<<Arg>>]
 
-  // CHECK-START: int Main.Xor0(int) instruction_simplifier (after)
-  // CHECK-NOT:                       Xor
+  /// CHECK-START: int Main.Xor0(int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Xor
 
   public static int Xor0(int arg) {
     return arg ^ 0;
   }
 
-  // CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<ConstF:i\d+>>   IntConstant -1
-  // CHECK-DAG:     <<Xor:i\d+>>      Xor [<<Arg>>,<<ConstF>>]
-  // CHECK-DAG:                       Return [<<Xor>>]
+  /// CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<ConstF:i\d+>>   IntConstant -1
+  /// CHECK-DAG:     <<Xor:i\d+>>      Xor [<<Arg>>,<<ConstF>>]
+  /// CHECK-DAG:                       Return [<<Xor>>]
 
-  // CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Not:i\d+>>      Not [<<Arg>>]
-  // CHECK-DAG:                       Return [<<Not>>]
+  /// CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Not:i\d+>>      Not [<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Not>>]
 
-  // CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after)
-  // CHECK-NOT:                       Xor
+  /// CHECK-START: int Main.XorAllOnes(int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Xor
 
   public static int XorAllOnes(int arg) {
     return arg ^ -1;
@@ -352,21 +352,21 @@
    * `InstructionSimplifierVisitor::TryMoveNegOnInputsAfterBinop`.
    */
 
-  // CHECK-START: int Main.AddNegs1(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
-  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
-  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Neg1>>,<<Neg2>>]
-  // CHECK-DAG:                       Return [<<Add>>]
+  /// CHECK-START: int Main.AddNegs1(int, int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
+  /// CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
+  /// CHECK-DAG:     <<Add:i\d+>>      Add [<<Neg1>>,<<Neg2>>]
+  /// CHECK-DAG:                       Return [<<Add>>]
 
-  // CHECK-START: int Main.AddNegs1(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-NOT:                       Neg
-  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Arg1>>,<<Arg2>>]
-  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Add>>]
-  // CHECK-DAG:                       Return [<<Neg>>]
+  /// CHECK-START: int Main.AddNegs1(int, int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-NOT:                       Neg
+  /// CHECK-DAG:     <<Add:i\d+>>      Add [<<Arg1>>,<<Arg2>>]
+  /// CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Add>>]
+  /// CHECK-DAG:                       Return [<<Neg>>]
 
   public static int AddNegs1(int arg1, int arg2) {
     return -arg1 + -arg2;
@@ -383,35 +383,35 @@
    * increasing the register pressure by creating or extending live ranges.
    */
 
-  // CHECK-START: int Main.AddNegs2(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
-  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
-  // CHECK-DAG:     <<Add1:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
-  // CHECK-DAG:     <<Add2:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
-  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Add1>>,<<Add2>>]
-  // CHECK-DAG:                       Return [<<Or>>]
+  /// CHECK-START: int Main.AddNegs2(int, int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
+  /// CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
+  /// CHECK-DAG:     <<Add1:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
+  /// CHECK-DAG:     <<Add2:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
+  /// CHECK-DAG:     <<Or:i\d+>>       Or [<<Add1>>,<<Add2>>]
+  /// CHECK-DAG:                       Return [<<Or>>]
 
-  // CHECK-START: int Main.AddNegs2(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
-  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
-  // CHECK-DAG:     <<Add1:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
-  // CHECK-DAG:     <<Add2:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
-  // CHECK-NOT:                       Neg
-  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Add1>>,<<Add2>>]
-  // CHECK-DAG:                       Return [<<Or>>]
+  /// CHECK-START: int Main.AddNegs2(int, int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
+  /// CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
+  /// CHECK-DAG:     <<Add1:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
+  /// CHECK-DAG:     <<Add2:i\d+>>     Add [<<Neg1>>,<<Neg2>>]
+  /// CHECK-NOT:                       Neg
+  /// CHECK-DAG:     <<Or:i\d+>>       Or [<<Add1>>,<<Add2>>]
+  /// CHECK-DAG:                       Return [<<Or>>]
 
-  // CHECK-START: int Main.AddNegs2(int, int) GVN (after)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
-  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
-  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Neg1>>,<<Neg2>>]
-  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Add>>,<<Add>>]
-  // CHECK-DAG:                       Return [<<Or>>]
+  /// CHECK-START: int Main.AddNegs2(int, int) GVN (after)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg1>>]
+  /// CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Arg2>>]
+  /// CHECK-DAG:     <<Add:i\d+>>      Add [<<Neg1>>,<<Neg2>>]
+  /// CHECK-DAG:     <<Or:i\d+>>       Or [<<Add>>,<<Add>>]
+  /// CHECK-DAG:                       Return [<<Or>>]
 
   public static int AddNegs2(int arg1, int arg2) {
     int temp1 = -arg1;
@@ -427,30 +427,30 @@
    * the loop.
    */
 
-  // CHECK-START: long Main.AddNegs3(long, long) instruction_simplifier (before)
-  // -------------- Arguments and initial negation operations.
-  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg1:j\d+>>     Neg [<<Arg1>>]
-  // CHECK-DAG:     <<Neg2:j\d+>>     Neg [<<Arg2>>]
-  // CHECK:                           Goto
-  // -------------- Loop
-  // CHECK:                           SuspendCheck
-  // CHECK:         <<Add:j\d+>>      Add [<<Neg1>>,<<Neg2>>]
-  // CHECK:                           Goto
+  /// CHECK-START: long Main.AddNegs3(long, long) instruction_simplifier (before)
+  //  -------------- Arguments and initial negation operations.
+  /// CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg1:j\d+>>     Neg [<<Arg1>>]
+  /// CHECK-DAG:     <<Neg2:j\d+>>     Neg [<<Arg2>>]
+  /// CHECK:                           Goto
+  //  -------------- Loop
+  /// CHECK:                           SuspendCheck
+  /// CHECK:         <<Add:j\d+>>      Add [<<Neg1>>,<<Neg2>>]
+  /// CHECK:                           Goto
 
-  // CHECK-START: long Main.AddNegs3(long, long) instruction_simplifier (after)
-  // -------------- Arguments and initial negation operations.
-  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg1:j\d+>>     Neg [<<Arg1>>]
-  // CHECK-DAG:     <<Neg2:j\d+>>     Neg [<<Arg2>>]
-  // CHECK:                           Goto
-  // -------------- Loop
-  // CHECK:                           SuspendCheck
-  // CHECK:         <<Add:j\d+>>      Add [<<Neg1>>,<<Neg2>>]
-  // CHECK-NOT:                       Neg
-  // CHECK:                           Goto
+  /// CHECK-START: long Main.AddNegs3(long, long) instruction_simplifier (after)
+  //  -------------- Arguments and initial negation operations.
+  /// CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg1:j\d+>>     Neg [<<Arg1>>]
+  /// CHECK-DAG:     <<Neg2:j\d+>>     Neg [<<Arg2>>]
+  /// CHECK:                           Goto
+  //  -------------- Loop
+  /// CHECK:                           SuspendCheck
+  /// CHECK:         <<Add:j\d+>>      Add [<<Neg1>>,<<Neg2>>]
+  /// CHECK-NOT:                       Neg
+  /// CHECK:                           Goto
 
   public static long AddNegs3(long arg1, long arg2) {
     long res = 0;
@@ -468,22 +468,22 @@
    * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitAdd`.
    */
 
-  // CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg1>>]
-  // CHECK-DAG:     <<Add:j\d+>>      Add [<<Neg>>,<<Arg2>>]
-  // CHECK-DAG:                       Return [<<Add>>]
+  /// CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg1>>]
+  /// CHECK-DAG:     <<Add:j\d+>>      Add [<<Neg>>,<<Arg2>>]
+  /// CHECK-DAG:                       Return [<<Add>>]
 
-  // CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Arg2>>,<<Arg1>>]
-  // CHECK-DAG:                       Return [<<Sub>>]
+  /// CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Arg2>>,<<Arg1>>]
+  /// CHECK-DAG:                       Return [<<Sub>>]
 
-  // CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after)
-  // CHECK-NOT:                       Neg
-  // CHECK-NOT:                       Add
+  /// CHECK-START: long Main.AddNeg1(long, long) instruction_simplifier (after)
+  /// CHECK-NOT:                       Neg
+  /// CHECK-NOT:                       Add
 
   public static long AddNeg1(long arg1, long arg2) {
     return -arg1 + arg2;
@@ -498,26 +498,26 @@
    * increasing the register pressure by creating or extending live ranges.
    */
 
-  // CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg2>>]
-  // CHECK-DAG:     <<Add1:j\d+>>     Add [<<Arg1>>,<<Neg>>]
-  // CHECK-DAG:     <<Add2:j\d+>>     Add [<<Arg1>>,<<Neg>>]
-  // CHECK-DAG:     <<Res:j\d+>>      Or [<<Add1>>,<<Add2>>]
-  // CHECK-DAG:                       Return [<<Res>>]
+  /// CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg2>>]
+  /// CHECK-DAG:     <<Add1:j\d+>>     Add [<<Arg1>>,<<Neg>>]
+  /// CHECK-DAG:     <<Add2:j\d+>>     Add [<<Arg1>>,<<Neg>>]
+  /// CHECK-DAG:     <<Res:j\d+>>      Or [<<Add1>>,<<Add2>>]
+  /// CHECK-DAG:                       Return [<<Res>>]
 
-  // CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg2>>]
-  // CHECK-DAG:     <<Add1:j\d+>>     Add [<<Arg1>>,<<Neg>>]
-  // CHECK-DAG:     <<Add2:j\d+>>     Add [<<Arg1>>,<<Neg>>]
-  // CHECK-DAG:     <<Res:j\d+>>      Or [<<Add1>>,<<Add2>>]
-  // CHECK-DAG:                       Return [<<Res>>]
+  /// CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg2>>]
+  /// CHECK-DAG:     <<Add1:j\d+>>     Add [<<Arg1>>,<<Neg>>]
+  /// CHECK-DAG:     <<Add2:j\d+>>     Add [<<Arg1>>,<<Neg>>]
+  /// CHECK-DAG:     <<Res:j\d+>>      Or [<<Add1>>,<<Add2>>]
+  /// CHECK-DAG:                       Return [<<Res>>]
 
-  // CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (after)
-  // CHECK-NOT:                       Sub
+  /// CHECK-START: long Main.AddNeg2(long, long) instruction_simplifier (after)
+  /// CHECK-NOT:                       Sub
 
   public static long AddNeg2(long arg1, long arg2) {
     long temp = -arg2;
@@ -529,18 +529,18 @@
    * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNeg`.
    */
 
-  // CHECK-START: long Main.NegNeg1(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:     <<Neg1:j\d+>>     Neg [<<Arg>>]
-  // CHECK-DAG:     <<Neg2:j\d+>>     Neg [<<Neg1>>]
-  // CHECK-DAG:                       Return [<<Neg2>>]
+  /// CHECK-START: long Main.NegNeg1(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Neg1:j\d+>>     Neg [<<Arg>>]
+  /// CHECK-DAG:     <<Neg2:j\d+>>     Neg [<<Neg1>>]
+  /// CHECK-DAG:                       Return [<<Neg2>>]
 
-  // CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:                       Return [<<Arg>>]
+  /// CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:                       Return [<<Arg>>]
 
-  // CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after)
-  // CHECK-NOT:                       Neg
+  /// CHECK-START: long Main.NegNeg1(long) instruction_simplifier (after)
+  /// CHECK-NOT:                       Neg
 
   public static long NegNeg1(long arg) {
     return -(-arg);
@@ -553,27 +553,27 @@
    * and in `InstructionSimplifierVisitor::VisitAdd`.
    */
 
-  // CHECK-START: int Main.NegNeg2(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg>>]
-  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Neg1>>]
-  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Neg1>>,<<Neg2>>]
-  // CHECK-DAG:                       Return [<<Add>>]
+  /// CHECK-START: int Main.NegNeg2(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Arg>>]
+  /// CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Neg1>>]
+  /// CHECK-DAG:     <<Add:i\d+>>      Add [<<Neg1>>,<<Neg2>>]
+  /// CHECK-DAG:                       Return [<<Add>>]
 
-  // CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg>>,<<Arg>>]
-  // CHECK-DAG:                       Return [<<Sub>>]
+  /// CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg>>,<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Sub>>]
 
-  // CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after)
-  // CHECK-NOT:                       Neg
-  // CHECK-NOT:                       Add
+  /// CHECK-START: int Main.NegNeg2(int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Neg
+  /// CHECK-NOT:                       Add
 
-  // CHECK-START: int Main.NegNeg2(int) constant_folding_after_inlining (after)
-  // CHECK:         <<Const0:i\d+>>   IntConstant 0
-  // CHECK-NOT:                       Neg
-  // CHECK-NOT:                       Add
-  // CHECK:                           Return [<<Const0>>]
+  /// CHECK-START: int Main.NegNeg2(int) constant_folding_after_inlining (after)
+  /// CHECK:         <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-NOT:                       Neg
+  /// CHECK-NOT:                       Add
+  /// CHECK:                           Return [<<Const0>>]
 
   public static int NegNeg2(int arg) {
     int temp = -arg;
@@ -587,20 +587,20 @@
    * and in `InstructionSimplifierVisitor::VisitSub`.
    */
 
-  // CHECK-START: long Main.NegNeg3(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
-  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg>>]
-  // CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Const0>>,<<Neg>>]
-  // CHECK-DAG:                       Return [<<Sub>>]
+  /// CHECK-START: long Main.NegNeg3(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:j\d+>>   LongConstant 0
+  /// CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg>>]
+  /// CHECK-DAG:     <<Sub:j\d+>>      Sub [<<Const0>>,<<Neg>>]
+  /// CHECK-DAG:                       Return [<<Sub>>]
 
-  // CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:                       Return [<<Arg>>]
+  /// CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:                       Return [<<Arg>>]
 
-  // CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after)
-  // CHECK-NOT:                       Neg
-  // CHECK-NOT:                       Sub
+  /// CHECK-START: long Main.NegNeg3(long) instruction_simplifier (after)
+  /// CHECK-NOT:                       Neg
+  /// CHECK-NOT:                       Sub
 
   public static long NegNeg3(long arg) {
     return 0 - -arg;
@@ -612,21 +612,21 @@
    * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNeg`.
    */
 
-  // CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg1>>,<<Arg2>>]
-  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Sub>>]
-  // CHECK-DAG:                       Return [<<Neg>>]
+  /// CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg1>>,<<Arg2>>]
+  /// CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Sub>>]
+  /// CHECK-DAG:                       Return [<<Neg>>]
 
-  // CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg2>>,<<Arg1>>]
-  // CHECK-DAG:                       Return [<<Sub>>]
+  /// CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg2>>,<<Arg1>>]
+  /// CHECK-DAG:                       Return [<<Sub>>]
 
-  // CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after)
-  // CHECK-NOT:                       Neg
+  /// CHECK-START: int Main.NegSub1(int, int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Neg
 
   public static int NegSub1(int arg1, int arg2) {
     return -(arg1 - arg2);
@@ -642,23 +642,23 @@
    * increasing the register pressure by creating or extending live ranges.
    */
 
-  // CHECK-START: int Main.NegSub2(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg1>>,<<Arg2>>]
-  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Sub>>]
-  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Sub>>]
-  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Neg1>>,<<Neg2>>]
-  // CHECK-DAG:                       Return [<<Or>>]
+  /// CHECK-START: int Main.NegSub2(int, int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg1>>,<<Arg2>>]
+  /// CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Sub>>]
+  /// CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Sub>>]
+  /// CHECK-DAG:     <<Or:i\d+>>       Or [<<Neg1>>,<<Neg2>>]
+  /// CHECK-DAG:                       Return [<<Or>>]
 
-  // CHECK-START: int Main.NegSub2(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg1>>,<<Arg2>>]
-  // CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Sub>>]
-  // CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Sub>>]
-  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Neg1>>,<<Neg2>>]
-  // CHECK-DAG:                       Return [<<Or>>]
+  /// CHECK-START: int Main.NegSub2(int, int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Arg1>>,<<Arg2>>]
+  /// CHECK-DAG:     <<Neg1:i\d+>>     Neg [<<Sub>>]
+  /// CHECK-DAG:     <<Neg2:i\d+>>     Neg [<<Sub>>]
+  /// CHECK-DAG:     <<Or:i\d+>>       Or [<<Neg1>>,<<Neg2>>]
+  /// CHECK-DAG:                       Return [<<Or>>]
 
   public static int NegSub2(int arg1, int arg2) {
     int temp = arg1 - arg2;
@@ -670,40 +670,40 @@
    * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitNot`.
    */
 
-  // CHECK-START: long Main.NotNot1(long) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:     <<ConstF1:j\d+>>  LongConstant -1
-  // CHECK-DAG:     <<Xor1:j\d+>>     Xor [<<Arg>>,<<ConstF1>>]
-  // CHECK-DAG:     <<Xor2:j\d+>>     Xor [<<Xor1>>,<<ConstF1>>]
-  // CHECK-DAG:                       Return [<<Xor2>>]
+  /// CHECK-START: long Main.NotNot1(long) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:     <<ConstF1:j\d+>>  LongConstant -1
+  /// CHECK-DAG:     <<Xor1:j\d+>>     Xor [<<Arg>>,<<ConstF1>>]
+  /// CHECK-DAG:     <<Xor2:j\d+>>     Xor [<<Xor1>>,<<ConstF1>>]
+  /// CHECK-DAG:                       Return [<<Xor2>>]
 
-  // CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
-  // CHECK-DAG:                       Return [<<Arg>>]
+  /// CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:j\d+>>      ParameterValue
+  /// CHECK-DAG:                       Return [<<Arg>>]
 
-  // CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
-  // CHECK-NOT:                       Xor
+  /// CHECK-START: long Main.NotNot1(long) instruction_simplifier (after)
+  /// CHECK-NOT:                       Xor
 
   public static long NotNot1(long arg) {
     return ~~arg;
   }
 
-  // CHECK-START: int Main.NotNot2(int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<ConstF1:i\d+>>  IntConstant -1
-  // CHECK-DAG:     <<Xor1:i\d+>>     Xor [<<Arg>>,<<ConstF1>>]
-  // CHECK-DAG:     <<Xor2:i\d+>>     Xor [<<Xor1>>,<<ConstF1>>]
-  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Xor1>>,<<Xor2>>]
-  // CHECK-DAG:                       Return [<<Add>>]
+  /// CHECK-START: int Main.NotNot2(int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<ConstF1:i\d+>>  IntConstant -1
+  /// CHECK-DAG:     <<Xor1:i\d+>>     Xor [<<Arg>>,<<ConstF1>>]
+  /// CHECK-DAG:     <<Xor2:i\d+>>     Xor [<<Xor1>>,<<ConstF1>>]
+  /// CHECK-DAG:     <<Add:i\d+>>      Add [<<Xor1>>,<<Xor2>>]
+  /// CHECK-DAG:                       Return [<<Add>>]
 
-  // CHECK-START: int Main.NotNot2(int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
-  // CHECK-DAG:     <<Not:i\d+>>      Not [<<Arg>>]
-  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Not>>,<<Arg>>]
-  // CHECK-DAG:                       Return [<<Add>>]
+  /// CHECK-START: int Main.NotNot2(int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Not:i\d+>>      Not [<<Arg>>]
+  /// CHECK-DAG:     <<Add:i\d+>>      Add [<<Not>>,<<Arg>>]
+  /// CHECK-DAG:                       Return [<<Add>>]
 
-  // CHECK-START: int Main.NotNot2(int) instruction_simplifier (after)
-  // CHECK-NOT:                       Xor
+  /// CHECK-START: int Main.NotNot2(int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Xor
 
   public static int NotNot2(int arg) {
     int temp = ~arg;
@@ -715,22 +715,22 @@
    * The transformation tested is implemented in `InstructionSimplifierVisitor::VisitSub`.
    */
 
-  // CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg1>>]
-  // CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Neg>>,<<Arg2>>]
-  // CHECK-DAG:                       Return [<<Sub>>]
+  /// CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg1>>]
+  /// CHECK-DAG:     <<Sub:i\d+>>      Sub [<<Neg>>,<<Arg2>>]
+  /// CHECK-DAG:                       Return [<<Sub>>]
 
-  // CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Add:i\d+>>      Add [<<Arg1>>,<<Arg2>>]
-  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Add>>]
-  // CHECK-DAG:                       Return [<<Neg>>]
+  /// CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Add:i\d+>>      Add [<<Arg1>>,<<Arg2>>]
+  /// CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Add>>]
+  /// CHECK-DAG:                       Return [<<Neg>>]
 
-  // CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (after)
-  // CHECK-NOT:                       Sub
+  /// CHECK-START: int Main.SubNeg1(int, int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Sub
 
   public static int SubNeg1(int arg1, int arg2) {
     return -arg1 - arg2;
@@ -746,26 +746,26 @@
    * increasing the register pressure by creating or extending live ranges.
    */
 
-  // CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg1>>]
-  // CHECK-DAG:     <<Sub1:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
-  // CHECK-DAG:     <<Sub2:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
-  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Sub1>>,<<Sub2>>]
-  // CHECK-DAG:                       Return [<<Or>>]
+  /// CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg1>>]
+  /// CHECK-DAG:     <<Sub1:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
+  /// CHECK-DAG:     <<Sub2:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
+  /// CHECK-DAG:     <<Or:i\d+>>       Or [<<Sub1>>,<<Sub2>>]
+  /// CHECK-DAG:                       Return [<<Or>>]
 
-  // CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg1>>]
-  // CHECK-DAG:     <<Sub1:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
-  // CHECK-DAG:     <<Sub2:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
-  // CHECK-DAG:     <<Or:i\d+>>       Or [<<Sub1>>,<<Sub2>>]
-  // CHECK-DAG:                       Return [<<Or>>]
+  /// CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg1:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:i\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg:i\d+>>      Neg [<<Arg1>>]
+  /// CHECK-DAG:     <<Sub1:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
+  /// CHECK-DAG:     <<Sub2:i\d+>>     Sub [<<Neg>>,<<Arg2>>]
+  /// CHECK-DAG:     <<Or:i\d+>>       Or [<<Sub1>>,<<Sub2>>]
+  /// CHECK-DAG:                       Return [<<Or>>]
 
-  // CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (after)
-  // CHECK-NOT:                       Add
+  /// CHECK-START: int Main.SubNeg2(int, int) instruction_simplifier (after)
+  /// CHECK-NOT:                       Add
 
   public static int SubNeg2(int arg1, int arg2) {
     int temp = -arg1;
@@ -779,28 +779,28 @@
    * the loop.
    */
 
-  // CHECK-START: long Main.SubNeg3(long, long) instruction_simplifier (before)
-  // -------------- Arguments and initial negation operation.
-  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg1>>]
-  // CHECK:                           Goto
-  // -------------- Loop
-  // CHECK:                           SuspendCheck
-  // CHECK:         <<Sub:j\d+>>      Sub [<<Neg>>,<<Arg2>>]
-  // CHECK:                           Goto
+  /// CHECK-START: long Main.SubNeg3(long, long) instruction_simplifier (before)
+  //  -------------- Arguments and initial negation operation.
+  /// CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg1>>]
+  /// CHECK:                           Goto
+  //  -------------- Loop
+  /// CHECK:                           SuspendCheck
+  /// CHECK:         <<Sub:j\d+>>      Sub [<<Neg>>,<<Arg2>>]
+  /// CHECK:                           Goto
 
-  // CHECK-START: long Main.SubNeg3(long, long) instruction_simplifier (after)
-  // -------------- Arguments and initial negation operation.
-  // CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
-  // CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg1>>]
-  // CHECK-DAG:                       Goto
-  // -------------- Loop
-  // CHECK:                           SuspendCheck
-  // CHECK:         <<Sub:j\d+>>      Sub [<<Neg>>,<<Arg2>>]
-  // CHECK-NOT:                       Neg
-  // CHECK:                           Goto
+  /// CHECK-START: long Main.SubNeg3(long, long) instruction_simplifier (after)
+  //  -------------- Arguments and initial negation operation.
+  /// CHECK-DAG:     <<Arg1:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Arg2:j\d+>>     ParameterValue
+  /// CHECK-DAG:     <<Neg:j\d+>>      Neg [<<Arg1>>]
+  /// CHECK-DAG:                       Goto
+  //  -------------- Loop
+  /// CHECK:                           SuspendCheck
+  /// CHECK:         <<Sub:j\d+>>      Sub [<<Neg>>,<<Arg2>>]
+  /// CHECK-NOT:                       Neg
+  /// CHECK:                           Goto
 
   public static long SubNeg3(long arg1, long arg2) {
     long res = 0;
@@ -811,117 +811,117 @@
     return res;
   }
 
-  // CHECK-START: int Main.EqualTrueRhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Arg>>,<<Const1>>]
-  // CHECK-DAG:                       If [<<Cond>>]
+  /// CHECK-START: int Main.EqualTrueRhs(boolean) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Arg>>,<<Const1>>]
+  /// CHECK-DAG:                       If [<<Cond>>]
 
-  // CHECK-START: int Main.EqualTrueRhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:                       If [<<Arg>>]
+  /// CHECK-START: int Main.EqualTrueRhs(boolean) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:                       If [<<Arg>>]
 
   public static int EqualTrueRhs(boolean arg) {
     return (arg != true) ? 3 : 5;
   }
 
-  // CHECK-START: int Main.EqualTrueLhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Const1>>,<<Arg>>]
-  // CHECK-DAG:                       If [<<Cond>>]
+  /// CHECK-START: int Main.EqualTrueLhs(boolean) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Const1>>,<<Arg>>]
+  /// CHECK-DAG:                       If [<<Cond>>]
 
-  // CHECK-START: int Main.EqualTrueLhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:                       If [<<Arg>>]
+  /// CHECK-START: int Main.EqualTrueLhs(boolean) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:                       If [<<Arg>>]
 
   public static int EqualTrueLhs(boolean arg) {
     return (true != arg) ? 3 : 5;
   }
 
-  // CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Arg>>,<<Const0>>]
-  // CHECK-DAG:                       If [<<Cond>>]
+  /// CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Arg>>,<<Const0>>]
+  /// CHECK-DAG:                       If [<<Cond>>]
 
-  // CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
-  // CHECK-DAG:                       If [<<NotArg>>]
+  /// CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  /// CHECK-DAG:                       If [<<NotArg>>]
 
   public static int EqualFalseRhs(boolean arg) {
     return (arg != false) ? 3 : 5;
   }
 
-  // CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Const0>>,<<Arg>>]
-  // CHECK-DAG:                       If [<<Cond>>]
+  /// CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Cond:z\d+>>     Equal [<<Const0>>,<<Arg>>]
+  /// CHECK-DAG:                       If [<<Cond>>]
 
-  // CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
-  // CHECK-DAG:                       If [<<NotArg>>]
+  /// CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  /// CHECK-DAG:                       If [<<NotArg>>]
 
   public static int EqualFalseLhs(boolean arg) {
     return (false != arg) ? 3 : 5;
   }
 
-  // CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Arg>>,<<Const1>>]
-  // CHECK-DAG:                       If [<<Cond>>]
+  /// CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Arg>>,<<Const1>>]
+  /// CHECK-DAG:                       If [<<Cond>>]
 
-  // CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
-  // CHECK-DAG:                       If [<<NotArg>>]
+  /// CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  /// CHECK-DAG:                       If [<<NotArg>>]
 
   public static int NotEqualTrueRhs(boolean arg) {
     return (arg == true) ? 3 : 5;
   }
 
-  // CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Const1>>,<<Arg>>]
-  // CHECK-DAG:                       If [<<Cond>>]
+  /// CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Const1>>,<<Arg>>]
+  /// CHECK-DAG:                       If [<<Cond>>]
 
-  // CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
-  // CHECK-DAG:                       If [<<NotArg>>]
+  /// CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<NotArg:z\d+>>   BooleanNot [<<Arg>>]
+  /// CHECK-DAG:                       If [<<NotArg>>]
 
   public static int NotEqualTrueLhs(boolean arg) {
     return (true == arg) ? 3 : 5;
   }
 
-  // CHECK-START: int Main.NotEqualFalseRhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Arg>>,<<Const0>>]
-  // CHECK-DAG:                       If [<<Cond>>]
+  /// CHECK-START: int Main.NotEqualFalseRhs(boolean) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Arg>>,<<Const0>>]
+  /// CHECK-DAG:                       If [<<Cond>>]
 
-  // CHECK-START: int Main.NotEqualFalseRhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:                       If [<<Arg>>]
+  /// CHECK-START: int Main.NotEqualFalseRhs(boolean) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:                       If [<<Arg>>]
 
   public static int NotEqualFalseRhs(boolean arg) {
     return (arg == false) ? 3 : 5;
   }
 
-  // CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier (before)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Const0>>,<<Arg>>]
-  // CHECK-DAG:                       If [<<Cond>>]
+  /// CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier (before)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Cond:z\d+>>     NotEqual [<<Const0>>,<<Arg>>]
+  /// CHECK-DAG:                       If [<<Cond>>]
 
-  // CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier (after)
-  // CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
-  // CHECK-DAG:                       If [<<Arg>>]
+  /// CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>      ParameterValue
+  /// CHECK-DAG:                       If [<<Arg>>]
 
   public static int NotEqualFalseLhs(boolean arg) {
     return (false == arg) ? 3 : 5;
@@ -933,20 +933,20 @@
    * remove the second.
    */
 
-  // CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_types (before)
-  // CHECK-DAG:     <<Arg:z\d+>>       ParameterValue
-  // CHECK-DAG:     <<NotArg:z\d+>>    BooleanNot [<<Arg>>]
-  // CHECK-DAG:     <<NotNotArg:z\d+>> BooleanNot [<<NotArg>>]
-  // CHECK-DAG:                        Return [<<NotNotArg>>]
+  /// CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_types (before)
+  /// CHECK-DAG:     <<Arg:z\d+>>       ParameterValue
+  /// CHECK-DAG:     <<NotArg:z\d+>>    BooleanNot [<<Arg>>]
+  /// CHECK-DAG:     <<NotNotArg:z\d+>> BooleanNot [<<NotArg>>]
+  /// CHECK-DAG:                        Return [<<NotNotArg>>]
 
-  // CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_types (after)
-  // CHECK-DAG:     <<Arg:z\d+>>       ParameterValue
-  // CHECK-DAG:                        BooleanNot [<<Arg>>]
-  // CHECK-DAG:                        Return [<<Arg>>]
+  /// CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_types (after)
+  /// CHECK-DAG:     <<Arg:z\d+>>       ParameterValue
+  /// CHECK-DAG:                        BooleanNot [<<Arg>>]
+  /// CHECK-DAG:                        Return [<<Arg>>]
 
-  // CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_types (after)
-  // CHECK:                            BooleanNot
-  // CHECK-NOT:                        BooleanNot
+  /// CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_types (after)
+  /// CHECK:                            BooleanNot
+  /// CHECK-NOT:                        BooleanNot
 
   public static boolean NegateValue(boolean arg) {
     return !arg;
@@ -956,76 +956,76 @@
     return !(NegateValue(arg));
   }
 
-  // CHECK-START: float Main.Div2(float) instruction_simplifier (before)
-  // CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
-  // CHECK-DAG:      <<Const2:f\d+>>   FloatConstant 2
-  // CHECK-DAG:      <<Div:f\d+>>      Div [<<Arg>>,<<Const2>>]
-  // CHECK-DAG:                        Return [<<Div>>]
+  /// CHECK-START: float Main.Div2(float) instruction_simplifier (before)
+  /// CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
+  /// CHECK-DAG:      <<Const2:f\d+>>   FloatConstant 2
+  /// CHECK-DAG:      <<Div:f\d+>>      Div [<<Arg>>,<<Const2>>]
+  /// CHECK-DAG:                        Return [<<Div>>]
 
-  // CHECK-START: float Main.Div2(float) instruction_simplifier (after)
-  // CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
-  // CHECK-DAG:      <<ConstP5:f\d+>>  FloatConstant 0.5
-  // CHECK-DAG:      <<Mul:f\d+>>      Mul [<<Arg>>,<<ConstP5>>]
-  // CHECK-DAG:                        Return [<<Mul>>]
+  /// CHECK-START: float Main.Div2(float) instruction_simplifier (after)
+  /// CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
+  /// CHECK-DAG:      <<ConstP5:f\d+>>  FloatConstant 0.5
+  /// CHECK-DAG:      <<Mul:f\d+>>      Mul [<<Arg>>,<<ConstP5>>]
+  /// CHECK-DAG:                        Return [<<Mul>>]
 
-  // CHECK-START: float Main.Div2(float) instruction_simplifier (after)
-  // CHECK-NOT:                        Div
+  /// CHECK-START: float Main.Div2(float) instruction_simplifier (after)
+  /// CHECK-NOT:                        Div
 
   public static float Div2(float arg) {
     return arg / 2.0f;
   }
 
-  // CHECK-START: double Main.Div2(double) instruction_simplifier (before)
-  // CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
-  // CHECK-DAG:      <<Const2:d\d+>>   DoubleConstant 2
-  // CHECK-DAG:      <<Div:d\d+>>      Div [<<Arg>>,<<Const2>>]
-  // CHECK-DAG:                        Return [<<Div>>]
+  /// CHECK-START: double Main.Div2(double) instruction_simplifier (before)
+  /// CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
+  /// CHECK-DAG:      <<Const2:d\d+>>   DoubleConstant 2
+  /// CHECK-DAG:      <<Div:d\d+>>      Div [<<Arg>>,<<Const2>>]
+  /// CHECK-DAG:                        Return [<<Div>>]
 
-  // CHECK-START: double Main.Div2(double) instruction_simplifier (after)
-  // CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
-  // CHECK-DAG:      <<ConstP5:d\d+>>  DoubleConstant 0.5
-  // CHECK-DAG:      <<Mul:d\d+>>      Mul [<<Arg>>,<<ConstP5>>]
-  // CHECK-DAG:                        Return [<<Mul>>]
+  /// CHECK-START: double Main.Div2(double) instruction_simplifier (after)
+  /// CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
+  /// CHECK-DAG:      <<ConstP5:d\d+>>  DoubleConstant 0.5
+  /// CHECK-DAG:      <<Mul:d\d+>>      Mul [<<Arg>>,<<ConstP5>>]
+  /// CHECK-DAG:                        Return [<<Mul>>]
 
-  // CHECK-START: double Main.Div2(double) instruction_simplifier (after)
-  // CHECK-NOT:                        Div
+  /// CHECK-START: double Main.Div2(double) instruction_simplifier (after)
+  /// CHECK-NOT:                        Div
   public static double Div2(double arg) {
     return arg / 2.0;
   }
 
-  // CHECK-START: float Main.DivMP25(float) instruction_simplifier (before)
-  // CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
-  // CHECK-DAG:      <<ConstMP25:f\d+>>   FloatConstant -0.25
-  // CHECK-DAG:      <<Div:f\d+>>      Div [<<Arg>>,<<ConstMP25>>]
-  // CHECK-DAG:                        Return [<<Div>>]
+  /// CHECK-START: float Main.DivMP25(float) instruction_simplifier (before)
+  /// CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
+  /// CHECK-DAG:      <<ConstMP25:f\d+>>   FloatConstant -0.25
+  /// CHECK-DAG:      <<Div:f\d+>>      Div [<<Arg>>,<<ConstMP25>>]
+  /// CHECK-DAG:                        Return [<<Div>>]
 
-  // CHECK-START: float Main.DivMP25(float) instruction_simplifier (after)
-  // CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
-  // CHECK-DAG:      <<ConstM4:f\d+>>  FloatConstant -4
-  // CHECK-DAG:      <<Mul:f\d+>>      Mul [<<Arg>>,<<ConstM4>>]
-  // CHECK-DAG:                        Return [<<Mul>>]
+  /// CHECK-START: float Main.DivMP25(float) instruction_simplifier (after)
+  /// CHECK-DAG:      <<Arg:f\d+>>      ParameterValue
+  /// CHECK-DAG:      <<ConstM4:f\d+>>  FloatConstant -4
+  /// CHECK-DAG:      <<Mul:f\d+>>      Mul [<<Arg>>,<<ConstM4>>]
+  /// CHECK-DAG:                        Return [<<Mul>>]
 
-  // CHECK-START: float Main.DivMP25(float) instruction_simplifier (after)
-  // CHECK-NOT:                        Div
+  /// CHECK-START: float Main.DivMP25(float) instruction_simplifier (after)
+  /// CHECK-NOT:                        Div
 
   public static float DivMP25(float arg) {
     return arg / -0.25f;
   }
 
-  // CHECK-START: double Main.DivMP25(double) instruction_simplifier (before)
-  // CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
-  // CHECK-DAG:      <<ConstMP25:d\d+>>   DoubleConstant -0.25
-  // CHECK-DAG:      <<Div:d\d+>>      Div [<<Arg>>,<<ConstMP25>>]
-  // CHECK-DAG:                        Return [<<Div>>]
+  /// CHECK-START: double Main.DivMP25(double) instruction_simplifier (before)
+  /// CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
+  /// CHECK-DAG:      <<ConstMP25:d\d+>>   DoubleConstant -0.25
+  /// CHECK-DAG:      <<Div:d\d+>>      Div [<<Arg>>,<<ConstMP25>>]
+  /// CHECK-DAG:                        Return [<<Div>>]
 
-  // CHECK-START: double Main.DivMP25(double) instruction_simplifier (after)
-  // CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
-  // CHECK-DAG:      <<ConstM4:d\d+>>  DoubleConstant -4
-  // CHECK-DAG:      <<Mul:d\d+>>      Mul [<<Arg>>,<<ConstM4>>]
-  // CHECK-DAG:                        Return [<<Mul>>]
+  /// CHECK-START: double Main.DivMP25(double) instruction_simplifier (after)
+  /// CHECK-DAG:      <<Arg:d\d+>>      ParameterValue
+  /// CHECK-DAG:      <<ConstM4:d\d+>>  DoubleConstant -4
+  /// CHECK-DAG:      <<Mul:d\d+>>      Mul [<<Arg>>,<<ConstM4>>]
+  /// CHECK-DAG:                        Return [<<Mul>>]
 
-  // CHECK-START: double Main.DivMP25(double) instruction_simplifier (after)
-  // CHECK-NOT:                        Div
+  /// CHECK-START: double Main.DivMP25(double) instruction_simplifier (after)
+  /// CHECK-NOT:                        Div
   public static double DivMP25(double arg) {
     return arg / -0.25f;
   }
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/462-checker-inlining-across-dex-files/src/Main.java b/test/462-checker-inlining-across-dex-files/src/Main.java
index 218c7ce..64979ca 100644
--- a/test/462-checker-inlining-across-dex-files/src/Main.java
+++ b/test/462-checker-inlining-across-dex-files/src/Main.java
@@ -21,105 +21,105 @@
 
 public class Main {
 
-  // CHECK-START: void Main.inlineEmptyMethod() inliner (before)
-  // CHECK-DAG:     <<Invoke:v\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      ReturnVoid
+  /// CHECK-START: void Main.inlineEmptyMethod() inliner (before)
+  /// CHECK-DAG:     <<Invoke:v\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      ReturnVoid
 
-  // CHECK-START: void Main.inlineEmptyMethod() inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: void Main.inlineEmptyMethod() inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
   public static void inlineEmptyMethod() {
     OtherDex.emptyMethod();
   }
 
-  // CHECK-START: int Main.inlineReturnIntMethod() inliner (before)
-  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: int Main.inlineReturnIntMethod() inliner (before)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: int Main.inlineReturnIntMethod() inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: int Main.inlineReturnIntMethod() inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
-  // CHECK-START: int Main.inlineReturnIntMethod() inliner (after)
-  // CHECK-DAG:     <<Const38:i\d+>> IntConstant 38
-  // CHECK-DAG:                      Return [<<Const38>>]
+  /// CHECK-START: int Main.inlineReturnIntMethod() inliner (after)
+  /// CHECK-DAG:     <<Const38:i\d+>> IntConstant 38
+  /// CHECK-DAG:                      Return [<<Const38>>]
 
   public static int inlineReturnIntMethod() {
     return OtherDex.returnIntMethod();
   }
 
-  // CHECK-START: int Main.dontInlineOtherDexStatic() inliner (before)
-  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: int Main.dontInlineOtherDexStatic() inliner (before)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: int Main.dontInlineOtherDexStatic() inliner (after)
-  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: int Main.dontInlineOtherDexStatic() inliner (after)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
   public static int dontInlineOtherDexStatic() {
     return OtherDex.returnOtherDexStatic();
   }
 
-  // CHECK-START: int Main.inlineMainStatic() inliner (before)
-  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: int Main.inlineMainStatic() inliner (before)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: int Main.inlineMainStatic() inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: int Main.inlineMainStatic() inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
-  // CHECK-START: int Main.inlineMainStatic() inliner (after)
-  // CHECK-DAG:     <<Static:i\d+>>  StaticFieldGet
-  // CHECK-DAG:                      Return [<<Static>>]
+  /// CHECK-START: int Main.inlineMainStatic() inliner (after)
+  /// CHECK-DAG:     <<Static:i\d+>>  StaticFieldGet
+  /// CHECK-DAG:                      Return [<<Static>>]
 
   public static int inlineMainStatic() {
     return OtherDex.returnMainStatic();
   }
 
-  // CHECK-START: int Main.dontInlineRecursiveCall() inliner (before)
-  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: int Main.dontInlineRecursiveCall() inliner (before)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: int Main.dontInlineRecursiveCall() inliner (after)
-  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: int Main.dontInlineRecursiveCall() inliner (after)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
   public static int dontInlineRecursiveCall() {
     return OtherDex.recursiveCall();
   }
 
-  // CHECK-START: java.lang.String Main.dontInlineReturnString() inliner (before)
-  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: java.lang.String Main.dontInlineReturnString() inliner (before)
+  /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: java.lang.String Main.dontInlineReturnString() inliner (after)
-  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: java.lang.String Main.dontInlineReturnString() inliner (after)
+  /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
   public static String dontInlineReturnString() {
     return OtherDex.returnString();
   }
 
-  // CHECK-START: java.lang.Class Main.dontInlineOtherDexClass() inliner (before)
-  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: java.lang.Class Main.dontInlineOtherDexClass() inliner (before)
+  /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: java.lang.Class Main.dontInlineOtherDexClass() inliner (after)
-  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: java.lang.Class Main.dontInlineOtherDexClass() inliner (after)
+  /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
   public static Class dontInlineOtherDexClass() {
     return OtherDex.returnOtherDexClass();
   }
 
-  // CHECK-START: java.lang.Class Main.inlineMainClass() inliner (before)
-  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: java.lang.Class Main.inlineMainClass() inliner (before)
+  /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: java.lang.Class Main.inlineMainClass() inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: java.lang.Class Main.inlineMainClass() inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
-  // CHECK-START: java.lang.Class Main.inlineMainClass() inliner (after)
-  // CHECK-DAG:                     Return [<<Class:l\d+>>]
-  // CHECK-DAG:     <<Class>>       LoadClass
+  /// CHECK-START: java.lang.Class Main.inlineMainClass() inliner (after)
+  /// CHECK-DAG:                     Return [<<Class:l\d+>>]
+  /// CHECK-DAG:     <<Class>>       LoadClass
   // Note: There are two LoadClass instructions. We obtain the correct
   //       instruction id by matching the Return's input list first.
 
@@ -127,28 +127,28 @@
     return OtherDex.returnMainClass();
   }
 
-  // CHECK-START: java.lang.Class Main.dontInlineOtherDexClassStaticCall() inliner (before)
-  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: java.lang.Class Main.dontInlineOtherDexClassStaticCall() inliner (before)
+  /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: java.lang.Class Main.dontInlineOtherDexClassStaticCall() inliner (after)
-  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: java.lang.Class Main.dontInlineOtherDexClassStaticCall() inliner (after)
+  /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
   public static Class dontInlineOtherDexClassStaticCall() {
     return OtherDex.returnOtherDexClassStaticCall();
   }
 
-  // CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (before)
-  // CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (before)
+  /// CHECK-DAG:     <<Invoke:l\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
-  // CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (after)
-  // CHECK-DAG:                     Return [<<Class:l\d+>>]
-  // CHECK-DAG:     <<Class>>       LoadClass
+  /// CHECK-START: java.lang.Class Main.inlineOtherDexCallingMain() inliner (after)
+  /// CHECK-DAG:                     Return [<<Class:l\d+>>]
+  /// CHECK-DAG:     <<Class>>       LoadClass
   // Note: There are two LoadClass instructions. We obtain the correct
   //       instruction id by matching the Return's input list first.
 
diff --git a/test/463-checker-boolean-simplifier/src/Main.java b/test/463-checker-boolean-simplifier/src/Main.java
index e237448..0b75930 100644
--- a/test/463-checker-boolean-simplifier/src/Main.java
+++ b/test/463-checker-boolean-simplifier/src/Main.java
@@ -37,33 +37,33 @@
    * empty branches removed.
    */
 
-  // CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (before)
-  // CHECK-DAG:     <<Param:z\d+>>    ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:                       If [<<Param>>]
-  // CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const1>>,<<Const0>>]
-  // CHECK-DAG:                       Return [<<Phi>>]
+  /// CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (before)
+  /// CHECK-DAG:     <<Param:z\d+>>    ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:                       If [<<Param>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const1>>,<<Const0>>]
+  /// CHECK-DAG:                       Return [<<Phi>>]
 
-  // CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (before)
-  // CHECK:                           Goto
-  // CHECK:                           Goto
-  // CHECK:                           Goto
-  // CHECK-NOT:                       Goto
+  /// CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (before)
+  /// CHECK:                           Goto
+  /// CHECK:                           Goto
+  /// CHECK:                           Goto
+  /// CHECK-NOT:                       Goto
 
-  // CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
-  // CHECK-DAG:     <<Param:z\d+>>    ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<NotParam:z\d+>> BooleanNot [<<Param>>]
-  // CHECK-DAG:                       Return [<<NotParam>>]
+  /// CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
+  /// CHECK-DAG:     <<Param:z\d+>>    ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<NotParam:z\d+>> BooleanNot [<<Param>>]
+  /// CHECK-DAG:                       Return [<<NotParam>>]
 
-  // CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
-  // CHECK-NOT:                       If
-  // CHECK-NOT:                       Phi
+  /// CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
+  /// CHECK-NOT:                       If
+  /// CHECK-NOT:                       Phi
 
-  // CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
-  // CHECK:                           Goto
-  // CHECK-NOT:                       Goto
+  /// CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
+  /// CHECK:                           Goto
+  /// CHECK-NOT:                       Goto
 
   public static boolean BooleanNot(boolean x) {
     return !x;
@@ -74,23 +74,23 @@
    * and 0 when False.
    */
 
-  // CHECK-START: boolean Main.GreaterThan(int, int) boolean_simplifier (before)
-  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<Cond:z\d+>>     GreaterThan [<<ParamX>>,<<ParamY>>]
-  // CHECK-DAG:                       If [<<Cond>>]
-  // CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const0>>,<<Const1>>]
-  // CHECK-DAG:                       Return [<<Phi>>]
+  /// CHECK-START: boolean Main.GreaterThan(int, int) boolean_simplifier (before)
+  /// CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<Cond:z\d+>>     GreaterThan [<<ParamX>>,<<ParamY>>]
+  /// CHECK-DAG:                       If [<<Cond>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const0>>,<<Const1>>]
+  /// CHECK-DAG:                       Return [<<Phi>>]
 
-  // CHECK-START: boolean Main.GreaterThan(int, int) boolean_simplifier (after)
-  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<Cond:z\d+>>     GreaterThan [<<ParamX>>,<<ParamY>>]
-  // CHECK-DAG:                       Return [<<Cond>>]
+  /// CHECK-START: boolean Main.GreaterThan(int, int) boolean_simplifier (after)
+  /// CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<Cond:z\d+>>     GreaterThan [<<ParamX>>,<<ParamY>>]
+  /// CHECK-DAG:                       Return [<<Cond>>]
 
   public static boolean GreaterThan(int x, int y) {
     return (x <= y) ? false : true;
@@ -101,26 +101,26 @@
    * and 1 when False.
    */
 
-  // CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (before)
-  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<Cond:z\d+>>     GreaterThanOrEqual [<<ParamX>>,<<ParamY>>]
-  // CHECK-DAG:                       If [<<Cond>>]
-  // CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const1>>,<<Const0>>]
-  // CHECK-DAG:                       Return [<<Phi>>]
+  /// CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (before)
+  /// CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<Cond:z\d+>>     GreaterThanOrEqual [<<ParamX>>,<<ParamY>>]
+  /// CHECK-DAG:                       If [<<Cond>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const1>>,<<Const0>>]
+  /// CHECK-DAG:                       Return [<<Phi>>]
 
-  // CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (after)
-  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<Cond:z\d+>>     LessThan [<<ParamX>>,<<ParamY>>]
-  // CHECK-DAG:                       Return [<<Cond>>]
+  /// CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (after)
+  /// CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<Cond:z\d+>>     LessThan [<<ParamX>>,<<ParamY>>]
+  /// CHECK-DAG:                       Return [<<Cond>>]
 
-  // CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (after)
-  // CHECK-NOT:                       GreaterThanOrEqual
+  /// CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (after)
+  /// CHECK-NOT:                       GreaterThanOrEqual
 
   public static boolean LessThan(int x, int y) {
     return (x < y) ? true : false;
@@ -131,57 +131,57 @@
    * Note that Phis are discovered retrospectively.
    */
 
-  // CHECK-START: boolean Main.ValuesOrdered(int, int, int) boolean_simplifier (before)
-  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<ParamZ:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-  // CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-  // CHECK-DAG:     <<CondXY:z\d+>>   GreaterThan [<<ParamX>>,<<ParamY>>]
-  // CHECK-DAG:                       If [<<CondXY>>]
-  // CHECK-DAG:     <<CondYZ:z\d+>>   GreaterThan [<<ParamY>>,<<ParamZ>>]
-  // CHECK-DAG:                       If [<<CondYZ>>]
-  // CHECK-DAG:     <<CondXYZ:z\d+>>  NotEqual [<<PhiXY:i\d+>>,<<PhiYZ:i\d+>>]
-  // CHECK-DAG:                       If [<<CondXYZ>>]
-  // CHECK-DAG:                       Return [<<PhiXYZ:i\d+>>]
-  // CHECK-DAG:     <<PhiXY>>         Phi [<<Const1>>,<<Const0>>]
-  // CHECK-DAG:     <<PhiYZ>>         Phi [<<Const1>>,<<Const0>>]
-  // CHECK-DAG:     <<PhiXYZ>>        Phi [<<Const1>>,<<Const0>>]
+  /// CHECK-START: boolean Main.ValuesOrdered(int, int, int) boolean_simplifier (before)
+  /// CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<ParamZ:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+  /// CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+  /// CHECK-DAG:     <<CondXY:z\d+>>   GreaterThan [<<ParamX>>,<<ParamY>>]
+  /// CHECK-DAG:                       If [<<CondXY>>]
+  /// CHECK-DAG:     <<CondYZ:z\d+>>   GreaterThan [<<ParamY>>,<<ParamZ>>]
+  /// CHECK-DAG:                       If [<<CondYZ>>]
+  /// CHECK-DAG:     <<CondXYZ:z\d+>>  NotEqual [<<PhiXY:i\d+>>,<<PhiYZ:i\d+>>]
+  /// CHECK-DAG:                       If [<<CondXYZ>>]
+  /// CHECK-DAG:                       Return [<<PhiXYZ:i\d+>>]
+  /// CHECK-DAG:     <<PhiXY>>         Phi [<<Const1>>,<<Const0>>]
+  /// CHECK-DAG:     <<PhiYZ>>         Phi [<<Const1>>,<<Const0>>]
+  /// CHECK-DAG:     <<PhiXYZ>>        Phi [<<Const1>>,<<Const0>>]
 
-  // CHECK-START: boolean Main.ValuesOrdered(int, int, int) boolean_simplifier (after)
-  // CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<ParamZ:i\d+>>   ParameterValue
-  // CHECK-DAG:     <<CmpXY:z\d+>>    LessThanOrEqual [<<ParamX>>,<<ParamY>>]
-  // CHECK-DAG:     <<CmpYZ:z\d+>>    LessThanOrEqual [<<ParamY>>,<<ParamZ>>]
-  // CHECK-DAG:     <<CmpXYZ:z\d+>>   Equal [<<CmpXY>>,<<CmpYZ>>]
-  // CHECK-DAG:                       Return [<<CmpXYZ>>]
+  /// CHECK-START: boolean Main.ValuesOrdered(int, int, int) boolean_simplifier (after)
+  /// CHECK-DAG:     <<ParamX:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<ParamY:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<ParamZ:i\d+>>   ParameterValue
+  /// CHECK-DAG:     <<CmpXY:z\d+>>    LessThanOrEqual [<<ParamX>>,<<ParamY>>]
+  /// CHECK-DAG:     <<CmpYZ:z\d+>>    LessThanOrEqual [<<ParamY>>,<<ParamZ>>]
+  /// CHECK-DAG:     <<CmpXYZ:z\d+>>   Equal [<<CmpXY>>,<<CmpYZ>>]
+  /// CHECK-DAG:                       Return [<<CmpXYZ>>]
 
   public static boolean ValuesOrdered(int x, int y, int z) {
     return (x <= y) == (y <= z);
   }
 
-  // CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (before)
-  // CHECK-DAG:     <<Param:z\d+>>    ParameterValue
-  // CHECK-DAG:     <<Const42:i\d+>>  IntConstant 42
-  // CHECK-DAG:     <<Const43:i\d+>>  IntConstant 43
-  // CHECK-DAG:     <<NotParam:z\d+>> BooleanNot [<<Param>>]
-  // CHECK-DAG:                       If [<<NotParam>>]
-  // CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const42>>,<<Const43>>]
-  // CHECK-DAG:                       Return [<<Phi>>]
+  /// CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (before)
+  /// CHECK-DAG:     <<Param:z\d+>>    ParameterValue
+  /// CHECK-DAG:     <<Const42:i\d+>>  IntConstant 42
+  /// CHECK-DAG:     <<Const43:i\d+>>  IntConstant 43
+  /// CHECK-DAG:     <<NotParam:z\d+>> BooleanNot [<<Param>>]
+  /// CHECK-DAG:                       If [<<NotParam>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const42>>,<<Const43>>]
+  /// CHECK-DAG:                       Return [<<Phi>>]
 
-  // CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (after)
-  // CHECK-DAG:     <<Param:z\d+>>    ParameterValue
-  // CHECK-DAG:     <<Const42:i\d+>>  IntConstant 42
-  // CHECK-DAG:     <<Const43:i\d+>>  IntConstant 43
-  // CHECK-DAG:                       If [<<Param>>]
-  // CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const42>>,<<Const43>>]
-  // CHECK-DAG:                       Return [<<Phi>>]
+  /// CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (after)
+  /// CHECK-DAG:     <<Param:z\d+>>    ParameterValue
+  /// CHECK-DAG:     <<Const42:i\d+>>  IntConstant 42
+  /// CHECK-DAG:     <<Const43:i\d+>>  IntConstant 43
+  /// CHECK-DAG:                       If [<<Param>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const42>>,<<Const43>>]
+  /// CHECK-DAG:                       Return [<<Phi>>]
 
   // Note: The fact that branches are swapped is verified by running the test.
 
-  // CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (after)
-  // CHECK-NOT:                       BooleanNot
+  /// CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (after)
+  /// CHECK-NOT:                       BooleanNot
 
   public static int NegatedCondition(boolean x) {
     if (x != false) {
diff --git a/test/464-checker-inline-sharpen-calls/src/Main.java b/test/464-checker-inline-sharpen-calls/src/Main.java
index e451f70..876496f 100644
--- a/test/464-checker-inline-sharpen-calls/src/Main.java
+++ b/test/464-checker-inline-sharpen-calls/src/Main.java
@@ -19,27 +19,27 @@
   public void invokeVirtual() {
   }
 
-  // CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) inliner (before)
-  // CHECK-DAG:     <<Invoke:v\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      ReturnVoid
+  /// CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) inliner (before)
+  /// CHECK-DAG:     <<Invoke:v\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      ReturnVoid
 
-  // CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
   public static void inlineSharpenInvokeVirtual(Main m) {
     m.invokeVirtual();
   }
 
-  // CHECK-START: int Main.inlineSharpenStringInvoke() inliner (before)
-  // CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
-  // CHECK-DAG:                      Return [<<Invoke>>]
+  /// CHECK-START: int Main.inlineSharpenStringInvoke() inliner (before)
+  /// CHECK-DAG:     <<Invoke:i\d+>>  InvokeStaticOrDirect
+  /// CHECK-DAG:                      Return [<<Invoke>>]
 
-  // CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
-  // CHECK-NOT:                      InvokeStaticOrDirect
+  /// CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
 
-  // CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
-  // CHECK-DAG:     <<Field:i\d+>>   InstanceFieldGet
-  // CHECK-DAG:                      Return [<<Field>>]
+  /// CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
+  /// CHECK-DAG:     <<Field:i\d+>>   InstanceFieldGet
+  /// CHECK-DAG:                      Return [<<Field>>]
 
   public static int inlineSharpenStringInvoke() {
     return "Foo".length();
diff --git a/test/465-checker-clinit-gvn/src/Main.java b/test/465-checker-clinit-gvn/src/Main.java
index ac2863c..704e9fe 100644
--- a/test/465-checker-clinit-gvn/src/Main.java
+++ b/test/465-checker-clinit-gvn/src/Main.java
@@ -26,31 +26,31 @@
 
 public final class Main {
 
-  // CHECK-START: int Main.accessTwoStatics() GVN (before)
-  // CHECK-DAG:     <<Class1:l\d+>>  LoadClass
-  // CHECK-DAG:                      ClinitCheck [<<Class1>>]
-  // CHECK-DAG:     <<Class2:l\d+>>  LoadClass
-  // CHECK-DAG:                      ClinitCheck [<<Class2>>]
+  /// CHECK-START: int Main.accessTwoStatics() GVN (before)
+  /// CHECK-DAG:     <<Class1:l\d+>>  LoadClass
+  /// CHECK-DAG:                      ClinitCheck [<<Class1>>]
+  /// CHECK-DAG:     <<Class2:l\d+>>  LoadClass
+  /// CHECK-DAG:                      ClinitCheck [<<Class2>>]
 
-  // CHECK-START: int Main.accessTwoStatics() GVN (after)
-  // CHECK-DAG:     <<Class:l\d+>>   LoadClass
-  // CHECK-DAG:                      ClinitCheck [<<Class>>]
-  // CHECK-NOT:                      ClinitCheck
+  /// CHECK-START: int Main.accessTwoStatics() GVN (after)
+  /// CHECK-DAG:     <<Class:l\d+>>   LoadClass
+  /// CHECK-DAG:                      ClinitCheck [<<Class>>]
+  /// CHECK-NOT:                      ClinitCheck
 
   public static int accessTwoStatics() {
     return OtherClass.b - OtherClass.a;
   }
 
-  // CHECK-START: int Main.accessTwoStaticsCallInBetween() GVN (before)
-  // CHECK-DAG:     <<Class1:l\d+>>  LoadClass
-  // CHECK-DAG:                      ClinitCheck [<<Class1>>]
-  // CHECK-DAG:     <<Class2:l\d+>>  LoadClass
-  // CHECK-DAG:                      ClinitCheck [<<Class2>>]
+  /// CHECK-START: int Main.accessTwoStaticsCallInBetween() GVN (before)
+  /// CHECK-DAG:     <<Class1:l\d+>>  LoadClass
+  /// CHECK-DAG:                      ClinitCheck [<<Class1>>]
+  /// CHECK-DAG:     <<Class2:l\d+>>  LoadClass
+  /// CHECK-DAG:                      ClinitCheck [<<Class2>>]
 
-  // CHECK-START: int Main.accessTwoStaticsCallInBetween() GVN (after)
-  // CHECK-DAG:     <<Class:l\d+>>   LoadClass
-  // CHECK-DAG:                      ClinitCheck [<<Class>>]
-  // CHECK-NOT:                      ClinitCheck
+  /// CHECK-START: int Main.accessTwoStaticsCallInBetween() GVN (after)
+  /// CHECK-DAG:     <<Class:l\d+>>   LoadClass
+  /// CHECK-DAG:                      ClinitCheck [<<Class>>]
+  /// CHECK-NOT:                      ClinitCheck
 
   public static int accessTwoStaticsCallInBetween() {
     int b = OtherClass.b;
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) {
diff --git a/test/466-get-live-vreg/src/Main.java b/test/466-get-live-vreg/src/Main.java
index 3118085..851506b 100644
--- a/test/466-get-live-vreg/src/Main.java
+++ b/test/466-get-live-vreg/src/Main.java
@@ -53,18 +53,30 @@
   }
 
   public static void main(String[] args) {
-    if (testLiveArgument(42) != 42) {
-      throw new Error("Expected 42");
+    if (testLiveArgument(staticField3) != staticField3) {
+      throw new Error("Expected " + staticField3);
     }
 
-    if (testLiveArgument(42) != 42) {
-      throw new Error("Expected 42");
+    if (testLiveArgument(staticField3) != staticField3) {
+      throw new Error("Expected " + staticField3);
     }
 
-    testIntervalHole(1, true);
-    testIntervalHole(1, false);
+    testWrapperIntervalHole(1, true);
+    testWrapperIntervalHole(1, false);
+  }
+
+  // Wrapper method to avoid inlining, which affects liveness
+  // of dex registers.
+  static void testWrapperIntervalHole(int arg, boolean test) {
+    try {
+      Thread.sleep(0);
+      testIntervalHole(arg, test);
+    } catch (Exception e) {
+      throw new Error(e);
+    }
   }
 
   static int staticField1;
   static int staticField2;
+  static int staticField3 = 42;
 }
diff --git a/test/468-checker-bool-simplifier-regression/smali/TestCase.smali b/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
index 33e6dc3..da1c5ec 100644
--- a/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
+++ b/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
@@ -18,18 +18,18 @@
 
 .field public static value:Z
 
-# CHECK-START: boolean TestCase.testCase() boolean_simplifier (before)
-# CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
-# CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
-# CHECK-DAG:     <<Value:z\d+>>    StaticFieldGet
-# CHECK-DAG:                       If [<<Value>>]
-# CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const1>>,<<Const0>>]
-# CHECK-DAG:                       Return [<<Phi>>]
+## CHECK-START: boolean TestCase.testCase() boolean_simplifier (before)
+## CHECK-DAG:     <<Const0:i\d+>>   IntConstant 0
+## CHECK-DAG:     <<Const1:i\d+>>   IntConstant 1
+## CHECK-DAG:     <<Value:z\d+>>    StaticFieldGet
+## CHECK-DAG:                       If [<<Value>>]
+## CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Const1>>,<<Const0>>]
+## CHECK-DAG:                       Return [<<Phi>>]
 
-# CHECK-START: boolean TestCase.testCase() boolean_simplifier (after)
-# CHECK-DAG:     <<Value:z\d+>>    StaticFieldGet
-# CHECK-DAG:     <<Not:z\d+>>      BooleanNot [<<Value>>]
-# CHECK-DAG:                       Return [<<Not>>]
+## CHECK-START: boolean TestCase.testCase() boolean_simplifier (after)
+## CHECK-DAG:     <<Value:z\d+>>    StaticFieldGet
+## CHECK-DAG:     <<Not:z\d+>>      BooleanNot [<<Value>>]
+## CHECK-DAG:                       Return [<<Not>>]
 
 .method public static testCase()Z
     .registers 2
diff --git a/test/473-checker-inliner-constants/src/Main.java b/test/473-checker-inliner-constants/src/Main.java
index 79d89b0..85f6565 100644
--- a/test/473-checker-inliner-constants/src/Main.java
+++ b/test/473-checker-inliner-constants/src/Main.java
@@ -16,13 +16,13 @@
 
 public class Main {
 
-  // CHECK-START: java.lang.Object Main.InlineNullConstant() inliner (before)
-  // CHECK:         NullConstant
-  // CHECK-NOT:     NullConstant
+  /// CHECK-START: java.lang.Object Main.InlineNullConstant() inliner (before)
+  /// CHECK:         NullConstant
+  /// CHECK-NOT:     NullConstant
 
-  // CHECK-START: java.lang.Object Main.InlineNullConstant() inliner (after)
-  // CHECK:         NullConstant
-  // CHECK-NOT:     NullConstant
+  /// CHECK-START: java.lang.Object Main.InlineNullConstant() inliner (after)
+  /// CHECK:         NullConstant
+  /// CHECK-NOT:     NullConstant
 
   public static Object returnNullConstant(Object x) {
     return null;
@@ -32,13 +32,13 @@
     return returnNullConstant(null);
   }
 
-  // CHECK-START: int Main.InlineIntConstant() inliner (before)
-  // CHECK:         IntConstant 42
-  // CHECK-NOT:     IntConstant 42
+  /// CHECK-START: int Main.InlineIntConstant() inliner (before)
+  /// CHECK:         IntConstant 42
+  /// CHECK-NOT:     IntConstant 42
 
-  // CHECK-START: int Main.InlineIntConstant() inliner (after)
-  // CHECK:         IntConstant 42
-  // CHECK-NOT:     IntConstant 42
+  /// CHECK-START: int Main.InlineIntConstant() inliner (after)
+  /// CHECK:         IntConstant 42
+  /// CHECK-NOT:     IntConstant 42
 
   public static int returnIntConstant(int x) {
     return 42;
@@ -48,13 +48,13 @@
     return returnIntConstant(42);
   }
 
-  // CHECK-START: long Main.InlineLongConstant() inliner (before)
-  // CHECK:         LongConstant 42
-  // CHECK-NOT:     LongConstant 42
+  /// CHECK-START: long Main.InlineLongConstant() inliner (before)
+  /// CHECK:         LongConstant 42
+  /// CHECK-NOT:     LongConstant 42
 
-  // CHECK-START: long Main.InlineLongConstant() inliner (after)
-  // CHECK:         LongConstant 42
-  // CHECK-NOT:     LongConstant 42
+  /// CHECK-START: long Main.InlineLongConstant() inliner (after)
+  /// CHECK:         LongConstant 42
+  /// CHECK-NOT:     LongConstant 42
 
   public static long returnLongConstant(long x) {
     return 42L;
diff --git a/test/474-checker-boolean-input/src/Main.java b/test/474-checker-boolean-input/src/Main.java
index 490f7f9..86d0f7c 100644
--- a/test/474-checker-boolean-input/src/Main.java
+++ b/test/474-checker-boolean-input/src/Main.java
@@ -27,9 +27,9 @@
    * we implement a suitable type analysis.
    */
 
-  // CHECK-START: boolean Main.TestPhiAsBoolean(int) boolean_simplifier (after)
-  // CHECK-DAG:     <<Phi:i\d+>>     Phi
-  // CHECK-DAG:                      BooleanNot [<<Phi>>]
+  /// CHECK-START: boolean Main.TestPhiAsBoolean(int) boolean_simplifier (after)
+  /// CHECK-DAG:     <<Phi:i\d+>>     Phi
+  /// CHECK-DAG:                      BooleanNot [<<Phi>>]
 
   public static boolean f1;
   public static boolean f2;
@@ -47,9 +47,9 @@
    * we implement a suitable type analysis.
    */
 
-  // CHECK-START: boolean Main.TestAndAsBoolean(boolean, boolean) boolean_simplifier (after)
-  // CHECK-DAG:     <<And:i\d+>>     And
-  // CHECK-DAG:                      BooleanNot [<<And>>]
+  /// CHECK-START: boolean Main.TestAndAsBoolean(boolean, boolean) boolean_simplifier (after)
+  /// CHECK-DAG:     <<And:i\d+>>     And
+  /// CHECK-DAG:                      BooleanNot [<<And>>]
 
   public static boolean InlineAnd(boolean x, boolean y) {
     return x & y;
@@ -64,9 +64,9 @@
    * we implement a suitable type analysis.
    */
 
-  // CHECK-START: boolean Main.TestOrAsBoolean(boolean, boolean) boolean_simplifier (after)
-  // CHECK-DAG:     <<Or:i\d+>>      Or
-  // CHECK-DAG:                      BooleanNot [<<Or>>]
+  /// CHECK-START: boolean Main.TestOrAsBoolean(boolean, boolean) boolean_simplifier (after)
+  /// CHECK-DAG:     <<Or:i\d+>>      Or
+  /// CHECK-DAG:                      BooleanNot [<<Or>>]
 
   public static boolean InlineOr(boolean x, boolean y) {
     return x | y;
@@ -81,9 +81,9 @@
    * we implement a suitable type analysis.
    */
 
-  // CHECK-START: boolean Main.TestXorAsBoolean(boolean, boolean) boolean_simplifier (after)
-  // CHECK-DAG:     <<Xor:i\d+>>     Xor
-  // CHECK-DAG:                      BooleanNot [<<Xor>>]
+  /// CHECK-START: boolean Main.TestXorAsBoolean(boolean, boolean) boolean_simplifier (after)
+  /// CHECK-DAG:     <<Xor:i\d+>>     Xor
+  /// CHECK-DAG:                      BooleanNot [<<Xor>>]
 
   public static boolean InlineXor(boolean x, boolean y) {
     return x ^ y;
diff --git a/test/476-checker-ctor-memory-barrier/src/Main.java b/test/476-checker-ctor-memory-barrier/src/Main.java
index f24dc4a..e709ba0 100644
--- a/test/476-checker-ctor-memory-barrier/src/Main.java
+++ b/test/476-checker-ctor-memory-barrier/src/Main.java
@@ -17,8 +17,8 @@
 // TODO: Add more tests after we can inline functions with calls.
 
 class ClassWithoutFinals {
-  // CHECK-START: void ClassWithoutFinals.<init>() register (after)
-  // CHECK-NOT: MemoryBarrier kind:StoreStore
+  /// CHECK-START: void ClassWithoutFinals.<init>() register (after)
+  /// CHECK-NOT: MemoryBarrier kind:StoreStore
   public ClassWithoutFinals() {}
 }
 
@@ -26,9 +26,9 @@
   public final int x;
   public ClassWithFinals obj;
 
-  // CHECK-START: void ClassWithFinals.<init>(boolean) register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void ClassWithFinals.<init>(boolean) register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
   public ClassWithFinals(boolean cond) {
     x = 0;
     if (cond) {
@@ -37,17 +37,17 @@
     }
   }
 
-  // CHECK-START: void ClassWithFinals.<init>() register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void ClassWithFinals.<init>() register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
   public ClassWithFinals() {
     x = 0;
   }
 
-  // CHECK-START: void ClassWithFinals.<init>(int) register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void ClassWithFinals.<init>(int) register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
   public ClassWithFinals(int x) {
     // This should have two barriers:
     //   - one for the constructor
@@ -58,33 +58,33 @@
 }
 
 class InheritFromClassWithFinals extends ClassWithFinals {
-  // CHECK-START: void InheritFromClassWithFinals.<init>() register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void InheritFromClassWithFinals.<init>() register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
 
-  // CHECK-START: void InheritFromClassWithFinals.<init>() register (after)
-  // CHECK-NOT:  InvokeStaticOrDirect
+  /// CHECK-START: void InheritFromClassWithFinals.<init>() register (after)
+  /// CHECK-NOT:  InvokeStaticOrDirect
   public InheritFromClassWithFinals() {
     // Should inline the super constructor.
   }
 
-  // CHECK-START: void InheritFromClassWithFinals.<init>(boolean) register (after)
-  // CHECK:      InvokeStaticOrDirect
+  /// CHECK-START: void InheritFromClassWithFinals.<init>(boolean) register (after)
+  /// CHECK:      InvokeStaticOrDirect
 
-  // CHECK-START: void InheritFromClassWithFinals.<init>(boolean) register (after)
-  // CHECK-NOT:  MemoryBarrier kind:StoreStore
+  /// CHECK-START: void InheritFromClassWithFinals.<init>(boolean) register (after)
+  /// CHECK-NOT:  MemoryBarrier kind:StoreStore
   public InheritFromClassWithFinals(boolean cond) {
     super(cond);
     // should not inline the super constructor
   }
 
-  // CHECK-START: void InheritFromClassWithFinals.<init>(int) register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK:      ReturnVoid
+  /// CHECK-START: void InheritFromClassWithFinals.<init>(int) register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK:      ReturnVoid
 
-  // CHECK-START: void InheritFromClassWithFinals.<init>(int) register (after)
-  // CHECK-NOT:  InvokeStaticOrDirect
+  /// CHECK-START: void InheritFromClassWithFinals.<init>(int) register (after)
+  /// CHECK-NOT:  InvokeStaticOrDirect
   public InheritFromClassWithFinals(int unused) {
     // Should inline the super constructor and insert a memory barrier.
 
@@ -96,35 +96,35 @@
 class HaveFinalsAndInheritFromClassWithFinals extends ClassWithFinals {
   final int y;
 
-  // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
 
-  // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() register (after)
-  // CHECK-NOT: InvokeStaticOrDirect
+  /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>() register (after)
+  /// CHECK-NOT: InvokeStaticOrDirect
   public HaveFinalsAndInheritFromClassWithFinals() {
     // Should inline the super constructor and remove the memory barrier.
     y = 0;
   }
 
-  // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(boolean) register (after)
-  // CHECK:      InvokeStaticOrDirect
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(boolean) register (after)
+  /// CHECK:      InvokeStaticOrDirect
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
   public HaveFinalsAndInheritFromClassWithFinals(boolean cond) {
     super(cond);
     // should not inline the super constructor
     y = 0;
   }
 
-  // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
 
-  // CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) register (after)
-  // CHECK-NOT:  InvokeStaticOrDirect
+  /// CHECK-START: void HaveFinalsAndInheritFromClassWithFinals.<init>(int) register (after)
+  /// CHECK-NOT:  InvokeStaticOrDirect
   public HaveFinalsAndInheritFromClassWithFinals(int unused) {
     // Should inline the super constructor and keep just one memory barrier.
     y = 0;
@@ -138,52 +138,52 @@
 
 public class Main {
 
-  // CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() register (after)
-  // CHECK:      InvokeStaticOrDirect
+  /// CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() register (after)
+  /// CHECK:      InvokeStaticOrDirect
 
-  // CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() register (after)
-  // CHECK-NOT:  MemoryBarrier kind:StoreStore
+  /// CHECK-START: ClassWithFinals Main.noInlineNoConstructorBarrier() register (after)
+  /// CHECK-NOT:  MemoryBarrier kind:StoreStore
   public static ClassWithFinals noInlineNoConstructorBarrier() {
     return new ClassWithFinals(false);
   }
 
-  // CHECK-START: void Main.inlineNew() register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void Main.inlineNew() register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
 
-  // CHECK-START: void Main.inlineNew() register (after)
-  // CHECK-NOT:  InvokeStaticOrDirect
+  /// CHECK-START: void Main.inlineNew() register (after)
+  /// CHECK-NOT:  InvokeStaticOrDirect
   public static void inlineNew() {
     new ClassWithFinals();
   }
 
-  // CHECK-START: void Main.inlineNew1() register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void Main.inlineNew1() register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
 
-  // CHECK-START: void Main.inlineNew1() register (after)
-  // CHECK-NOT:  InvokeStaticOrDirect
+  /// CHECK-START: void Main.inlineNew1() register (after)
+  /// CHECK-NOT:  InvokeStaticOrDirect
   public static void inlineNew1() {
     new InheritFromClassWithFinals();
   }
 
-  // CHECK-START: void Main.inlineNew2() register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void Main.inlineNew2() register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
 
-  // CHECK-START: void Main.inlineNew2() register (after)
-  // CHECK-NOT:  InvokeStaticOrDirect
+  /// CHECK-START: void Main.inlineNew2() register (after)
+  /// CHECK-NOT:  InvokeStaticOrDirect
   public static void inlineNew2() {
     new HaveFinalsAndInheritFromClassWithFinals();
   }
 
-  // CHECK-START: void Main.inlineNew3() register (after)
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK:      MemoryBarrier kind:StoreStore
-  // CHECK-NEXT: ReturnVoid
+  /// CHECK-START: void Main.inlineNew3() register (after)
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK:      MemoryBarrier kind:StoreStore
+  /// CHECK-NEXT: ReturnVoid
 
-  // CHECK-START: void Main.inlineNew3() register (after)
-  // CHECK-NOT:  InvokeStaticOrDirect
+  /// CHECK-START: void Main.inlineNew3() register (after)
+  /// CHECK-NOT:  InvokeStaticOrDirect
   public static void inlineNew3() {
     new HaveFinalsAndInheritFromClassWithFinals();
     new HaveFinalsAndInheritFromClassWithFinals();
diff --git a/test/477-checker-bound-type/src/Main.java b/test/477-checker-bound-type/src/Main.java
index b30028d..fe52e83 100644
--- a/test/477-checker-bound-type/src/Main.java
+++ b/test/477-checker-bound-type/src/Main.java
@@ -17,8 +17,8 @@
 
 public class Main {
 
-  // CHECK-START: java.lang.Object Main.boundTypeForIf(java.lang.Object) reference_type_propagation (after)
-  // CHECK:     BoundType
+  /// CHECK-START: java.lang.Object Main.boundTypeForIf(java.lang.Object) reference_type_propagation (after)
+  /// CHECK:     BoundType
   public static Object boundTypeForIf(Object a) {
     if (a != null) {
       return a.toString();
@@ -27,8 +27,8 @@
     }
   }
 
-  // CHECK-START: java.lang.Object Main.boundTypeForInstanceOf(java.lang.Object) reference_type_propagation (after)
-  // CHECK:     BoundType
+  /// CHECK-START: java.lang.Object Main.boundTypeForInstanceOf(java.lang.Object) reference_type_propagation (after)
+  /// CHECK:     BoundType
   public static Object boundTypeForInstanceOf(Object a) {
     if (a instanceof Main) {
       return (Main)a;
@@ -37,8 +37,8 @@
     }
   }
 
-  // CHECK-START: java.lang.Object Main.noBoundTypeForIf(java.lang.Object) reference_type_propagation (after)
-  // CHECK-NOT: BoundType
+  /// CHECK-START: java.lang.Object Main.noBoundTypeForIf(java.lang.Object) reference_type_propagation (after)
+  /// CHECK-NOT: BoundType
   public static Object noBoundTypeForIf(Object a) {
     if (a == null) {
       return new Object();
@@ -47,8 +47,8 @@
     }
   }
 
-  // CHECK-START: java.lang.Object Main.noBoundTypeForInstanceOf(java.lang.Object) reference_type_propagation (after)
-  // CHECK-NOT: BoundType
+  /// CHECK-START: java.lang.Object Main.noBoundTypeForInstanceOf(java.lang.Object) reference_type_propagation (after)
+  /// CHECK-NOT: BoundType
   public static Object noBoundTypeForInstanceOf(Object a) {
     if (a instanceof Main) {
       return new Object();
diff --git a/test/478-checker-clinit-check-pruning/src/Main.java b/test/478-checker-clinit-check-pruning/src/Main.java
index e8739b8..51be912 100644
--- a/test/478-checker-clinit-check-pruning/src/Main.java
+++ b/test/478-checker-clinit-check-pruning/src/Main.java
@@ -23,17 +23,17 @@
    * removed before register allocation & code generation.
    */
 
-  // CHECK-START: void Main.invokeStaticInlined() builder (after)
-  // CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
-  // CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
-  // CHECK-DAG:                           InvokeStaticOrDirect [<<ClinitCheck>>]
+  /// CHECK-START: void Main.invokeStaticInlined() builder (after)
+  /// CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
+  /// CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
+  /// CHECK-DAG:                           InvokeStaticOrDirect [<<ClinitCheck>>]
 
-  // CHECK-START: void Main.invokeStaticInlined() inliner (after)
-  // CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
-  // CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
+  /// CHECK-START: void Main.invokeStaticInlined() inliner (after)
+  /// CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
+  /// CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
 
-  // CHECK-START: void Main.invokeStaticInlined() inliner (after)
-  // CHECK-NOT:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main.invokeStaticInlined() inliner (after)
+  /// CHECK-NOT:                           InvokeStaticOrDirect
 
   // The following checks ensure the clinit check instruction added by
   // the builder is pruned by the PrepareForRegisterAllocation, while
@@ -41,12 +41,12 @@
   // graph is not dumped after (nor before) this step, we check the
   // CFG as it is before the next pass (liveness analysis) instead.
 
-  // CHECK-START: void Main.invokeStaticInlined() liveness (before)
-  // CHECK-DAG:                           LoadClass gen_clinit_check:true
+  /// CHECK-START: void Main.invokeStaticInlined() liveness (before)
+  /// CHECK-DAG:                           LoadClass gen_clinit_check:true
 
-  // CHECK-START: void Main.invokeStaticInlined() liveness (before)
-  // CHECK-NOT:                           ClinitCheck
-  // CHECK-NOT:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main.invokeStaticInlined() liveness (before)
+  /// CHECK-NOT:                           ClinitCheck
+  /// CHECK-NOT:                           InvokeStaticOrDirect
 
   static void invokeStaticInlined() {
     ClassWithClinit1.$opt$inline$StaticMethod();
@@ -66,15 +66,15 @@
    * initialization check of the called method's declaring class.
    */
 
-  // CHECK-START: void Main.invokeStaticNotInlined() builder (after)
-  // CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
-  // CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
-  // CHECK-DAG:                           InvokeStaticOrDirect [<<ClinitCheck>>]
+  /// CHECK-START: void Main.invokeStaticNotInlined() builder (after)
+  /// CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
+  /// CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
+  /// CHECK-DAG:                           InvokeStaticOrDirect [<<ClinitCheck>>]
 
-  // CHECK-START: void Main.invokeStaticNotInlined() inliner (after)
-  // CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
-  // CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
-  // CHECK-DAG:                           InvokeStaticOrDirect [<<ClinitCheck>>]
+  /// CHECK-START: void Main.invokeStaticNotInlined() inliner (after)
+  /// CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
+  /// CHECK-DAG:     <<ClinitCheck:l\d+>>  ClinitCheck [<<LoadClass>>]
+  /// CHECK-DAG:                           InvokeStaticOrDirect [<<ClinitCheck>>]
 
   // The following checks ensure the clinit check and load class
   // instructions added by the builder are pruned by the
@@ -82,12 +82,12 @@
   // dumped after (nor before) this step, we check the CFG as it is
   // before the next pass (liveness analysis) instead.
 
-  // CHECK-START: void Main.invokeStaticNotInlined() liveness (before)
-  // CHECK-DAG:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main.invokeStaticNotInlined() liveness (before)
+  /// CHECK-DAG:                           InvokeStaticOrDirect
 
-  // CHECK-START: void Main.invokeStaticNotInlined() liveness (before)
-  // CHECK-NOT:                           LoadClass
-  // CHECK-NOT:                           ClinitCheck
+  /// CHECK-START: void Main.invokeStaticNotInlined() liveness (before)
+  /// CHECK-NOT:                           LoadClass
+  /// CHECK-NOT:                           ClinitCheck
 
   static void invokeStaticNotInlined() {
     ClassWithClinit2.staticMethod();
@@ -114,17 +114,17 @@
    * explicit clinit check.
    */
 
-  // CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after)
-  // CHECK-DAG:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after)
+  /// CHECK-DAG:                           InvokeStaticOrDirect
 
-  // CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after)
-  // CHECK-NOT:                           LoadClass
-  // CHECK-NOT:                           ClinitCheck
+  /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() builder (after)
+  /// CHECK-NOT:                           LoadClass
+  /// CHECK-NOT:                           ClinitCheck
 
-  // CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() inliner (after)
-  // CHECK-NOT:                           LoadClass
-  // CHECK-NOT:                           ClinitCheck
-  // CHECK-NOT:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main$ClassWithClinit3.invokeStaticInlined() inliner (after)
+  /// CHECK-NOT:                           LoadClass
+  /// CHECK-NOT:                           ClinitCheck
+  /// CHECK-NOT:                           InvokeStaticOrDirect
 
   static class ClassWithClinit3 {
     static void invokeStaticInlined() {
@@ -149,25 +149,25 @@
    * require an explicit clinit check.
    */
 
-  // CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after)
-  // CHECK-DAG:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after)
+  /// CHECK-DAG:                           InvokeStaticOrDirect
 
-  // CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after)
-  // CHECK-NOT:                           LoadClass
-  // CHECK-NOT:                           ClinitCheck
+  /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() builder (after)
+  /// CHECK-NOT:                           LoadClass
+  /// CHECK-NOT:                           ClinitCheck
 
-  // CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after)
-  // CHECK-DAG:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after)
+  /// CHECK-DAG:                           InvokeStaticOrDirect
 
-  // CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after)
-  // CHECK-NOT:                           LoadClass
-  // CHECK-NOT:                           ClinitCheck
+  /// CHECK-START: void Main$ClassWithClinit4.invokeStaticNotInlined() inliner (after)
+  /// CHECK-NOT:                           LoadClass
+  /// CHECK-NOT:                           ClinitCheck
 
   static class ClassWithClinit4 {
     static void invokeStaticNotInlined() {
       // The invocation of invokeStaticNotInlined triggers the
       // initialization of ClassWithClinit4, meaning that the
-      // hereinbelow call to staticMethod does not need a clinit
+      // call to staticMethod below does not need a clinit
       // check.
       staticMethod();
     }
@@ -192,17 +192,17 @@
    * explicit clinit check.
    */
 
-  // CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after)
-  // CHECK-DAG:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after)
+  /// CHECK-DAG:                           InvokeStaticOrDirect
 
-  // CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after)
-  // CHECK-NOT:                           LoadClass
-  // CHECK-NOT:                           ClinitCheck
+  /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() builder (after)
+  /// CHECK-NOT:                           LoadClass
+  /// CHECK-NOT:                           ClinitCheck
 
-  // CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() inliner (after)
-  // CHECK-NOT:                           LoadClass
-  // CHECK-NOT:                           ClinitCheck
-  // CHECK-NOT:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main$SubClassOfClassWithClinit5.invokeStaticInlined() inliner (after)
+  /// CHECK-NOT:                           LoadClass
+  /// CHECK-NOT:                           ClinitCheck
+  /// CHECK-NOT:                           InvokeStaticOrDirect
 
   static class ClassWithClinit5 {
     static void $opt$inline$StaticMethod() {
@@ -225,19 +225,19 @@
    * explicit clinit check.
    */
 
-  // CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after)
-  // CHECK-DAG:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after)
+  /// CHECK-DAG:                           InvokeStaticOrDirect
 
-  // CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after)
-  // CHECK-NOT:                           LoadClass
-  // CHECK-NOT:                           ClinitCheck
+  /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() builder (after)
+  /// CHECK-NOT:                           LoadClass
+  /// CHECK-NOT:                           ClinitCheck
 
-  // CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after)
-  // CHECK-DAG:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after)
+  /// CHECK-DAG:                           InvokeStaticOrDirect
 
-  // CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after)
-  // CHECK-NOT:                           LoadClass
-  // CHECK-NOT:                           ClinitCheck
+  /// CHECK-START: void Main$SubClassOfClassWithClinit6.invokeStaticNotInlined() inliner (after)
+  /// CHECK-NOT:                           LoadClass
+  /// CHECK-NOT:                           ClinitCheck
 
   static class ClassWithClinit6 {
     static boolean doThrow = false;
@@ -266,14 +266,14 @@
    * we don't do generate a clinit check.
    */
 
-  // CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before)
-  // CHECK-DAG:     <<IntConstant:i\d+>>  IntConstant 0
-  // CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
-  // CHECK-DAG:                           InvokeStaticOrDirect
-  // CHECK-DAG:                           StaticFieldSet [<<LoadClass>>,<<IntConstant>>]
+  /// CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before)
+  /// CHECK-DAG:     <<IntConstant:i\d+>>  IntConstant 0
+  /// CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:false
+  /// CHECK-DAG:                           InvokeStaticOrDirect
+  /// CHECK-DAG:                           StaticFieldSet [<<LoadClass>>,<<IntConstant>>]
 
-  // CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before)
-  // CHECK-NOT:                           ClinitCheck
+  /// CHECK-START: void Main.noClinitBecauseOfInvokeStatic() liveness (before)
+  /// CHECK-NOT:                           ClinitCheck
 
   static void noClinitBecauseOfInvokeStatic() {
     ClassWithClinit2.staticMethod();
@@ -285,14 +285,14 @@
    * will generate a clinit check.
    */
 
-  // CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before)
-  // CHECK-DAG:     <<IntConstant:i\d+>>  IntConstant 0
-  // CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:true
-  // CHECK-DAG:                           StaticFieldSet [<<LoadClass>>,<<IntConstant>>]
-  // CHECK-DAG:                           InvokeStaticOrDirect
+  /// CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before)
+  /// CHECK-DAG:     <<IntConstant:i\d+>>  IntConstant 0
+  /// CHECK-DAG:     <<LoadClass:l\d+>>    LoadClass gen_clinit_check:true
+  /// CHECK-DAG:                           StaticFieldSet [<<LoadClass>>,<<IntConstant>>]
+  /// CHECK-DAG:                           InvokeStaticOrDirect
 
-  // CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before)
-  // CHECK-NOT:                           ClinitCheck
+  /// CHECK-START: void Main.clinitBecauseOfFieldAccess() liveness (before)
+  /// CHECK-NOT:                           ClinitCheck
   static void clinitBecauseOfFieldAccess() {
     ClassWithClinit2.doThrow = false;
     ClassWithClinit2.staticMethod();
diff --git a/test/478-checker-inliner-nested-loop/src/Main.java b/test/478-checker-inliner-nested-loop/src/Main.java
index df583d9..aa02349 100644
--- a/test/478-checker-inliner-nested-loop/src/Main.java
+++ b/test/478-checker-inliner-nested-loop/src/Main.java
@@ -33,12 +33,12 @@
     return result;
   }
 
-  // CHECK-START: int Main.NestedLoop(int, int) inliner (before)
-  // CHECK-NOT:     Mul
+  /// CHECK-START: int Main.NestedLoop(int, int) inliner (before)
+  /// CHECK-NOT:     Mul
 
-  // CHECK-START: int Main.NestedLoop(int, int) inliner (after)
-  // CHECK:         Mul
-  // CHECK-NOT:     Mul
+  /// CHECK-START: int Main.NestedLoop(int, int) inliner (after)
+  /// CHECK:         Mul
+  /// CHECK-NOT:     Mul
 
   public static int NestedLoop(int max_x, int max_y) {
     int total = 0;
diff --git a/test/480-checker-dead-blocks/src/Main.java b/test/480-checker-dead-blocks/src/Main.java
index b76755e..4cc1634 100644
--- a/test/480-checker-dead-blocks/src/Main.java
+++ b/test/480-checker-dead-blocks/src/Main.java
@@ -30,25 +30,25 @@
     return false;
   }
 
-  // CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (before)
-  // CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
-  // CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
-  // CHECK-DAG:                      If
-  // CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
-  // CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
-  // CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
-  // CHECK-DAG:                      Return [<<Phi>>]
+  /// CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (before)
+  /// CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
+  /// CHECK-DAG:                      If
+  /// CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
+  /// CHECK-DAG:                      Return [<<Phi>>]
 
-  // CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (after)
-  // CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
-  // CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
-  // CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
-  // CHECK-DAG:                      Return [<<Add>>]
+  /// CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (after)
+  /// CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:                      Return [<<Add>>]
 
-  // CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (after)
-  // CHECK-NOT:                      If
-  // CHECK-NOT:                      Sub
-  // CHECK-NOT:                      Phi
+  /// CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (after)
+  /// CHECK-NOT:                      If
+  /// CHECK-NOT:                      Sub
+  /// CHECK-NOT:                      Phi
 
   public static int testTrueBranch(int x, int y) {
     int z;
@@ -60,25 +60,25 @@
     return z;
   }
 
-  // CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (before)
-  // CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
-  // CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
-  // CHECK-DAG:                      If
-  // CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
-  // CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
-  // CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
-  // CHECK-DAG:                      Return [<<Phi>>]
+  /// CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (before)
+  /// CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
+  /// CHECK-DAG:                      If
+  /// CHECK-DAG:     <<Add:i\d+>>     Add [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:     <<Phi:i\d+>>     Phi [<<Add>>,<<Sub>>]
+  /// CHECK-DAG:                      Return [<<Phi>>]
 
-  // CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (after)
-  // CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
-  // CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
-  // CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
-  // CHECK-DAG:                      Return [<<Sub>>]
+  /// CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (after)
+  /// CHECK-DAG:     <<ArgX:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<ArgY:i\d+>>    ParameterValue
+  /// CHECK-DAG:     <<Sub:i\d+>>     Sub [<<ArgX>>,<<ArgY>>]
+  /// CHECK-DAG:                      Return [<<Sub>>]
 
-  // CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (after)
-  // CHECK-NOT:                      If
-  // CHECK-NOT:                      Add
-  // CHECK-NOT:                      Phi
+  /// CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (after)
+  /// CHECK-NOT:                      If
+  /// CHECK-NOT:                      Add
+  /// CHECK-NOT:                      Phi
 
   public static int testFalseBranch(int x, int y) {
     int z;
@@ -90,11 +90,11 @@
     return z;
   }
 
-  // CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination_final (before)
-  // CHECK:                          Mul
+  /// CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination_final (before)
+  /// CHECK:                          Mul
 
-  // CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination_final (after)
-  // CHECK-NOT:                      Mul
+  /// CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination_final (after)
+  /// CHECK-NOT:                      Mul
 
   public static int testRemoveLoop(int x) {
     if (inlineFalse()) {
@@ -105,13 +105,13 @@
     return x;
   }
 
-  // CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination_final (before)
-  // CHECK-DAG:                      Return
-  // CHECK-DAG:                      Exit
+  /// CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination_final (before)
+  /// CHECK-DAG:                      Return
+  /// CHECK-DAG:                      Exit
 
-  // CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination_final (after)
-  // CHECK-NOT:                      Return
-  // CHECK-NOT:                      Exit
+  /// CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination_final (after)
+  /// CHECK-NOT:                      Return
+  /// CHECK-NOT:                      Exit
 
   public static int testInfiniteLoop(int x) {
     while (inlineTrue()) {
@@ -120,17 +120,17 @@
     return x;
   }
 
-  // CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (before)
-  // CHECK-DAG:                      If
-  // CHECK-DAG:                      Add
+  /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (before)
+  /// CHECK-DAG:                      If
+  /// CHECK-DAG:                      Add
 
-  // CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (after)
-  // CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
-  // CHECK-DAG:                      Return [<<Arg>>]
+  /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
+  /// CHECK-DAG:                      Return [<<Arg>>]
 
-  // CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (after)
-  // CHECK-NOT:                      If
-  // CHECK-NOT:                      Add
+  /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (after)
+  /// CHECK-NOT:                      If
+  /// CHECK-NOT:                      Add
 
   public static int testDeadLoop(int x) {
     while (inlineFalse()) {
@@ -139,18 +139,18 @@
     return x;
   }
 
-  // CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (before)
-  // CHECK-DAG:                      If
-  // CHECK-DAG:                      If
-  // CHECK-DAG:                      Add
+  /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (before)
+  /// CHECK-DAG:                      If
+  /// CHECK-DAG:                      If
+  /// CHECK-DAG:                      Add
 
-  // CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (after)
-  // CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
-  // CHECK-DAG:                      Return [<<Arg>>]
+  /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (after)
+  /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
+  /// CHECK-DAG:                      Return [<<Arg>>]
 
-  // CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (after)
-  // CHECK-NOT:                      If
-  // CHECK-NOT:                      Add
+  /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (after)
+  /// CHECK-NOT:                      If
+  /// CHECK-NOT:                      Add
 
   public static int testUpdateLoopInformation(int x) {
     // Use of Or in the condition generates a dead loop where not all of its
@@ -161,16 +161,16 @@
     return x;
   }
 
-  // CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination_final (before)
-  // CHECK:                          SuspendCheck
-  // CHECK:                          SuspendCheck
-  // CHECK:                          SuspendCheck
-  // CHECK-NOT:                      SuspendCheck
+  /// CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination_final (before)
+  /// CHECK:                          SuspendCheck
+  /// CHECK:                          SuspendCheck
+  /// CHECK:                          SuspendCheck
+  /// CHECK-NOT:                      SuspendCheck
 
-  // CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination_final (after)
-  // CHECK:                          SuspendCheck
-  // CHECK:                          SuspendCheck
-  // CHECK-NOT:                      SuspendCheck
+  /// CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination_final (after)
+  /// CHECK:                          SuspendCheck
+  /// CHECK:                          SuspendCheck
+  /// CHECK-NOT:                      SuspendCheck
 
   public static int testRemoveSuspendCheck(int x, int y) {
     // Inner loop will leave behind the header with its SuspendCheck. DCE must
diff --git a/test/482-checker-loop-back-edge-use/src/Main.java b/test/482-checker-loop-back-edge-use/src/Main.java
index 0ed9267..5754723 100644
--- a/test/482-checker-loop-back-edge-use/src/Main.java
+++ b/test/482-checker-loop-back-edge-use/src/Main.java
@@ -17,17 +17,17 @@
 
 public class Main {
 
-  // CHECK-START: void Main.loop1(boolean) liveness (after)
-  // CHECK:         ParameterValue  liveness:2  ranges:{[2,22)} uses:[17,22]
-  // CHECK:         Goto            liveness:20
+  /// CHECK-START: void Main.loop1(boolean) liveness (after)
+  /// CHECK:         ParameterValue  liveness:2  ranges:{[2,22)} uses:[17,22]
+  /// CHECK:         Goto            liveness:20
   public static void loop1(boolean incoming) {
     while (incoming) {}
   }
 
-  // CHECK-START: void Main.loop2(boolean) liveness (after)
-  // CHECK:         ParameterValue  liveness:2  ranges:{[2,42)} uses:[33,38,42]
-  // CHECK:         Goto            liveness:36
-  // CHECK:         Goto            liveness:40
+  /// CHECK-START: void Main.loop2(boolean) liveness (after)
+  /// CHECK:         ParameterValue  liveness:4  ranges:{[4,44)} uses:[35,40,44]
+  /// CHECK:         Goto            liveness:38
+  /// CHECK:         Goto            liveness:42
   public static void loop2(boolean incoming) {
     while (true) {
       System.out.println("foo");
@@ -35,12 +35,12 @@
     }
   }
 
-  // CHECK-START: void Main.loop3(boolean) liveness (after)
-  // CHECK:         ParameterValue  liveness:2  ranges:{[2,60)} uses:[56,60]
-  // CHECK:         Goto            liveness:58
+  /// CHECK-START: void Main.loop3(boolean) liveness (after)
+  /// CHECK:         ParameterValue  liveness:4  ranges:{[4,62)} uses:[58,62]
+  /// CHECK:         Goto            liveness:60
 
-  // CHECK-START: void Main.loop3(boolean) liveness (after)
-  // CHECK-NOT:     Goto liveness:54
+  /// CHECK-START: void Main.loop3(boolean) liveness (after)
+  /// CHECK-NOT:     Goto liveness:56
   public static void loop3(boolean incoming) {
     // 'incoming' only needs a use at the outer loop's back edge.
     while (System.currentTimeMillis() != 42) {
@@ -49,11 +49,11 @@
     }
   }
 
-  // CHECK-START: void Main.loop4(boolean) liveness (after)
-  // CHECK:         ParameterValue  liveness:2  ranges:{[2,22)} uses:[22]
+  /// CHECK-START: void Main.loop4(boolean) liveness (after)
+  /// CHECK:         ParameterValue  liveness:4  ranges:{[4,24)} uses:[24]
 
-  // CHECK-START: void Main.loop4(boolean) liveness (after)
-  // CHECK-NOT:     Goto            liveness:20
+  /// CHECK-START: void Main.loop4(boolean) liveness (after)
+  /// CHECK-NOT:     Goto            liveness:22
   public static void loop4(boolean incoming) {
     // 'incoming' has no loop use, so should not have back edge uses.
     System.out.println(incoming);
@@ -62,10 +62,10 @@
     }
   }
 
-  // CHECK-START: void Main.loop5(boolean) liveness (after)
-  // CHECK:         ParameterValue  liveness:2  ranges:{[2,50)} uses:[33,42,46,50]
-  // CHECK:         Goto            liveness:44
-  // CHECK:         Goto            liveness:48
+  /// CHECK-START: void Main.loop5(boolean) liveness (after)
+  /// CHECK:         ParameterValue  liveness:4  ranges:{[4,52)} uses:[35,44,48,52]
+  /// CHECK:         Goto            liveness:46
+  /// CHECK:         Goto            liveness:50
   public static void loop5(boolean incoming) {
     // 'incoming' must have a use at both back edges.
     while (Runtime.getRuntime() != null) {
@@ -75,12 +75,12 @@
     }
   }
 
-  // CHECK-START: void Main.loop6(boolean) liveness (after)
-  // CHECK          ParameterValue  liveness:2  ranges:{[2,46)} uses:[24,46]
-  // CHECK:         Goto            liveness:44
+  /// CHECK-START: void Main.loop6(boolean) liveness (after)
+  /// CHECK:         ParameterValue  liveness:4  ranges:{[4,48)} uses:[26,48]
+  /// CHECK:         Goto            liveness:46
 
-  // CHECK-START: void Main.loop6(boolean) liveness (after)
-  // CHECK-NOT:     Goto            liveness:22
+  /// CHECK-START: void Main.loop6(boolean) liveness (after)
+  /// CHECK-NOT:     Goto            liveness:24
   public static void loop6(boolean incoming) {
     // 'incoming' must have a use only at the first loop's back edge.
     while (true) {
@@ -89,10 +89,10 @@
     }
   }
 
-  // CHECK-START: void Main.loop7(boolean) liveness (after)
-  // CHECK:         ParameterValue  liveness:2  ranges:{[2,50)} uses:[32,41,46,50]
-  // CHECK:         Goto            liveness:44
-  // CHECK:         Goto            liveness:48
+  /// CHECK-START: void Main.loop7(boolean) liveness (after)
+  /// CHECK:         ParameterValue  liveness:4  ranges:{[4,52)} uses:[34,43,48,52]
+  /// CHECK:         Goto            liveness:46
+  /// CHECK:         Goto            liveness:50
   public static void loop7(boolean incoming) {
     // 'incoming' must have a use at both back edges.
     while (Runtime.getRuntime() != null) {
@@ -101,10 +101,10 @@
     }
   }
 
-  // CHECK-START: void Main.loop8() liveness (after)
-  // CHECK:         StaticFieldGet  liveness:12 ranges:{[12,44)} uses:[35,40,44]
-  // CHECK:         Goto            liveness:38
-  // CHECK:         Goto            liveness:42
+  /// CHECK-START: void Main.loop8() liveness (after)
+  /// CHECK:         StaticFieldGet  liveness:14 ranges:{[14,46)} uses:[37,42,46]
+  /// CHECK:         Goto            liveness:40
+  /// CHECK:         Goto            liveness:44
   public static void loop8() {
     // 'incoming' must have a use at both back edges.
     boolean incoming = field;
@@ -113,9 +113,9 @@
     }
   }
 
-  // CHECK-START: void Main.loop9() liveness (after)
-  // CHECK:         StaticFieldGet  liveness:22 ranges:{[22,36)} uses:[31,36]
-  // CHECK:         Goto            liveness:38
+  /// CHECK-START: void Main.loop9() liveness (after)
+  /// CHECK:         StaticFieldGet  liveness:24 ranges:{[24,38)} uses:[33,38]
+  /// CHECK:         Goto            liveness:40
   public static void loop9() {
     while (Runtime.getRuntime() != null) {
       // 'incoming' must only have a use in the inner loop.
diff --git a/test/484-checker-register-hints/src/Main.java b/test/484-checker-register-hints/src/Main.java
index 33952d9..3715ca2 100644
--- a/test/484-checker-register-hints/src/Main.java
+++ b/test/484-checker-register-hints/src/Main.java
@@ -16,21 +16,21 @@
 
 public class Main {
 
-  // CHECK-START: void Main.test1(boolean, int, int, int, int, int) register (after)
-  // CHECK:       name "B0"
-  // CHECK-NOT:     ParallelMove
-  // CHECK:       name "B1"
-  // CHECK-NOT:   end_block
-  // CHECK:         If
-  // CHECK-NOT:     ParallelMove
-  // CHECK:       name "B3"
-  // CHECK-NOT:   end_block
-  // CHECK:         ArraySet
+  /// CHECK-START: void Main.test1(boolean, int, int, int, int, int) register (after)
+  /// CHECK:       name "B0"
+  /// CHECK-NOT:     ParallelMove
+  /// CHECK:       name "B1"
+  /// CHECK-NOT:   end_block
+  /// CHECK:         If
+  /// CHECK-NOT:     ParallelMove
+  /// CHECK:       name "B3"
+  /// CHECK-NOT:   end_block
+  /// CHECK:         ArraySet
   // We could check here that there is a parallel move, but it's only valid
   // for some architectures (for example x86), as other architectures may
   // not do move at all.
-  // CHECK:       end_block
-  // CHECK-NOT:     ParallelMove
+  /// CHECK:       end_block
+  /// CHECK-NOT:     ParallelMove
 
   public static void test1(boolean z, int a, int b, int c, int d, int m) {
     int e = live1;
@@ -51,21 +51,21 @@
     live1 = e + f + g;
   }
 
-  // CHECK-START: void Main.test2(boolean, int, int, int, int, int) register (after)
-  // CHECK:       name "B0"
-  // CHECK-NOT:     ParallelMove
-  // CHECK:       name "B1"
-  // CHECK-NOT:   end_block
-  // CHECK:         If
-  // CHECK-NOT:     ParallelMove
-  // CHECK:       name "B3"
-  // CHECK-NOT:   end_block
-  // CHECK:         ArraySet
+  /// CHECK-START: void Main.test2(boolean, int, int, int, int, int) register (after)
+  /// CHECK:       name "B0"
+  /// CHECK-NOT:     ParallelMove
+  /// CHECK:       name "B1"
+  /// CHECK-NOT:   end_block
+  /// CHECK:         If
+  /// CHECK-NOT:     ParallelMove
+  /// CHECK:       name "B3"
+  /// CHECK-NOT:   end_block
+  /// CHECK:         ArraySet
   // We could check here that there is a parallel move, but it's only valid
   // for some architectures (for example x86), as other architectures may
   // not do move at all.
-  // CHECK:       end_block
-  // CHECK-NOT:     ParallelMove
+  /// CHECK:       end_block
+  /// CHECK-NOT:     ParallelMove
 
   public static void test2(boolean z, int a, int b, int c, int d, int m) {
     int e = live1;
@@ -85,21 +85,21 @@
     live1 = e + f + g;
   }
 
-  // CHECK-START: void Main.test3(boolean, int, int, int, int, int) register (after)
-  // CHECK:       name "B0"
-  // CHECK-NOT:     ParallelMove
-  // CHECK:       name "B1"
-  // CHECK-NOT:   end_block
-  // CHECK:         If
-  // CHECK-NOT:     ParallelMove
-  // CHECK:       name "B6"
-  // CHECK-NOT:   end_block
-  // CHECK:         ArraySet
+  /// CHECK-START: void Main.test3(boolean, int, int, int, int, int) register (after)
+  /// CHECK:       name "B0"
+  /// CHECK-NOT:     ParallelMove
+  /// CHECK:       name "B1"
+  /// CHECK-NOT:   end_block
+  /// CHECK:         If
+  /// CHECK-NOT:     ParallelMove
+  /// CHECK:       name "B6"
+  /// CHECK-NOT:   end_block
+  /// CHECK:         ArraySet
   // We could check here that there is a parallel move, but it's only valid
   // for some architectures (for example x86), as other architectures may
   // not do move at all.
-  // CHECK:       end_block
-  // CHECK-NOT:     ParallelMove
+  /// CHECK:       end_block
+  /// CHECK-NOT:     ParallelMove
 
   public static void test3(boolean z, int a, int b, int c, int d, int m) {
     // Same version as test2, but with branches reversed, to ensure
diff --git a/test/485-checker-dce-loop-update/smali/TestCase.smali b/test/485-checker-dce-loop-update/smali/TestCase.smali
index 487a5df..da27bf6 100644
--- a/test/485-checker-dce-loop-update/smali/TestCase.smali
+++ b/test/485-checker-dce-loop-update/smali/TestCase.smali
@@ -23,27 +23,27 @@
 .end method
 
 
-# CHECK-START: int TestCase.testSingleExit(int, boolean) dead_code_elimination_final (before)
-# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
-# CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
-# CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
-# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
-# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
-# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
-# CHECK-DAG:                    If [<<Cst1>>]                              loop:<<HeaderY>>
-# CHECK-DAG:     <<Add5>>       Add [<<PhiX>>,<<Cst5>>]                    loop:<<HeaderY>>
-# CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
-# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+## CHECK-START: int TestCase.testSingleExit(int, boolean) dead_code_elimination_final (before)
+## CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+## CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
+## CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
+## CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+## CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
+## CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+## CHECK-DAG:                    If [<<Cst1>>]                              loop:<<HeaderY>>
+## CHECK-DAG:     <<Add5>>       Add [<<PhiX>>,<<Cst5>>]                    loop:<<HeaderY>>
+## CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+## CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
 
-# CHECK-START: int TestCase.testSingleExit(int, boolean) dead_code_elimination_final (after)
-# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
-# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
-# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<AddX:i\d+>>]               loop:<<HeaderY:B\d+>>
-# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
-# CHECK-DAG:     <<AddX>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
-# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+## CHECK-START: int TestCase.testSingleExit(int, boolean) dead_code_elimination_final (after)
+## CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+## CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+## CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<AddX:i\d+>>]               loop:<<HeaderY:B\d+>>
+## CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+## CHECK-DAG:     <<AddX>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+## CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
 
 .method public static testSingleExit(IZ)I
   .registers 3
@@ -73,31 +73,31 @@
 .end method
 
 
-# CHECK-START: int TestCase.testMultipleExits(int, boolean, boolean) dead_code_elimination_final (before)
-# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
-# CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
-# CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
-# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
-# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
-# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
-# CHECK-DAG:                    If [<<ArgZ>>]                              loop:<<HeaderY>>
-# CHECK-DAG:                    If [<<Cst1>>]                              loop:<<HeaderY>>
-# CHECK-DAG:     <<Add5>>       Add [<<PhiX>>,<<Cst5>>]                    loop:<<HeaderY>>
-# CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
-# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+## CHECK-START: int TestCase.testMultipleExits(int, boolean, boolean) dead_code_elimination_final (before)
+## CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+## CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
+## CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
+## CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+## CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
+## CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+## CHECK-DAG:                    If [<<ArgZ>>]                              loop:<<HeaderY>>
+## CHECK-DAG:                    If [<<Cst1>>]                              loop:<<HeaderY>>
+## CHECK-DAG:     <<Add5>>       Add [<<PhiX>>,<<Cst5>>]                    loop:<<HeaderY>>
+## CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+## CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
 
-# CHECK-START: int TestCase.testMultipleExits(int, boolean, boolean) dead_code_elimination_final (after)
-# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
-# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
-# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add7:i\d+>>]               loop:<<HeaderY:B\d+>>
-# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
-# CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
-# CHECK-DAG:                    If [<<ArgZ>>]                              loop:none
-# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+## CHECK-START: int TestCase.testMultipleExits(int, boolean, boolean) dead_code_elimination_final (after)
+## CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+## CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+## CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add7:i\d+>>]               loop:<<HeaderY:B\d+>>
+## CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+## CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+## CHECK-DAG:                    If [<<ArgZ>>]                              loop:none
+## CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
 
 .method public static testMultipleExits(IZZ)I
   .registers 4
@@ -129,37 +129,37 @@
 .end method
 
 
-# CHECK-START: int TestCase.testExitPredecessors(int, boolean, boolean) dead_code_elimination_final (before)
-# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
-# CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
-# CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
-# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
-# CHECK-DAG:     <<Cst9:i\d+>>  IntConstant 9
-# CHECK-DAG:     <<PhiX1:i\d+>> Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
-# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
-# CHECK-DAG:                    If [<<ArgZ>>]                              loop:<<HeaderY>>
-# CHECK-DAG:     <<Mul9:i\d+>>  Mul [<<PhiX1>>,<<Cst9>>]                   loop:<<HeaderY>>
-# CHECK-DAG:     <<PhiX2:i\d+>> Phi [<<Mul9>>,<<PhiX1>>]                   loop:<<HeaderY>>
-# CHECK-DAG:                    If [<<Cst1>>]                              loop:<<HeaderY>>
-# CHECK-DAG:     <<Add5>>       Add [<<PhiX2>>,<<Cst5>>]                   loop:<<HeaderY>>
-# CHECK-DAG:     <<Add7>>       Add [<<PhiX1>>,<<Cst7>>]                   loop:<<HeaderY>>
-# CHECK-DAG:                    Return [<<PhiX2>>]                         loop:none
+## CHECK-START: int TestCase.testExitPredecessors(int, boolean, boolean) dead_code_elimination_final (before)
+## CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+## CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
+## CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
+## CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+## CHECK-DAG:     <<Cst9:i\d+>>  IntConstant 9
+## CHECK-DAG:     <<PhiX1:i\d+>> Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
+## CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+## CHECK-DAG:                    If [<<ArgZ>>]                              loop:<<HeaderY>>
+## CHECK-DAG:     <<Mul9:i\d+>>  Mul [<<PhiX1>>,<<Cst9>>]                   loop:<<HeaderY>>
+## CHECK-DAG:     <<PhiX2:i\d+>> Phi [<<Mul9>>,<<PhiX1>>]                   loop:<<HeaderY>>
+## CHECK-DAG:                    If [<<Cst1>>]                              loop:<<HeaderY>>
+## CHECK-DAG:     <<Add5>>       Add [<<PhiX2>>,<<Cst5>>]                   loop:<<HeaderY>>
+## CHECK-DAG:     <<Add7>>       Add [<<PhiX1>>,<<Cst7>>]                   loop:<<HeaderY>>
+## CHECK-DAG:                    Return [<<PhiX2>>]                         loop:none
 
-# CHECK-START: int TestCase.testExitPredecessors(int, boolean, boolean) dead_code_elimination_final (after)
-# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
-# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
-# CHECK-DAG:     <<Cst9:i\d+>>  IntConstant 9
-# CHECK-DAG:     <<PhiX1:i\d+>> Phi [<<ArgX>>,<<Add7:i\d+>>]               loop:<<HeaderY:B\d+>>
-# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
-# CHECK-DAG:     <<Add7>>       Add [<<PhiX1>>,<<Cst7>>]                   loop:<<HeaderY>>
-# CHECK-DAG:                    If [<<ArgZ>>]                              loop:none
-# CHECK-DAG:     <<Mul9:i\d+>>  Mul [<<PhiX1>>,<<Cst9>>]                   loop:none
-# CHECK-DAG:     <<PhiX2:i\d+>> Phi [<<Mul9>>,<<PhiX1>>]                   loop:none
-# CHECK-DAG:                    Return [<<PhiX2>>]                         loop:none
+## CHECK-START: int TestCase.testExitPredecessors(int, boolean, boolean) dead_code_elimination_final (after)
+## CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+## CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+## CHECK-DAG:     <<Cst9:i\d+>>  IntConstant 9
+## CHECK-DAG:     <<PhiX1:i\d+>> Phi [<<ArgX>>,<<Add7:i\d+>>]               loop:<<HeaderY:B\d+>>
+## CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+## CHECK-DAG:     <<Add7>>       Add [<<PhiX1>>,<<Cst7>>]                   loop:<<HeaderY>>
+## CHECK-DAG:                    If [<<ArgZ>>]                              loop:none
+## CHECK-DAG:     <<Mul9:i\d+>>  Mul [<<PhiX1>>,<<Cst9>>]                   loop:none
+## CHECK-DAG:     <<PhiX2:i\d+>> Phi [<<Mul9>>,<<PhiX1>>]                   loop:none
+## CHECK-DAG:                    Return [<<PhiX2>>]                         loop:none
 
 .method public static testExitPredecessors(IZZ)I
   .registers 4
@@ -196,48 +196,48 @@
 .end method
 
 
-# CHECK-START: int TestCase.testInnerLoop(int, boolean, boolean) dead_code_elimination_final (before)
-# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
-# CHECK-DAG:     <<Cst0:i\d+>>  IntConstant 0
-# CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
-# CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
-# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+## CHECK-START: int TestCase.testInnerLoop(int, boolean, boolean) dead_code_elimination_final (before)
+## CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+## CHECK-DAG:     <<Cst0:i\d+>>  IntConstant 0
+## CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
+## CHECK-DAG:     <<Cst5:i\d+>>  IntConstant 5
+## CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
 #
-# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
-# CHECK-DAG:     <<PhiZ1:i\d+>> Phi [<<ArgZ>>,<<XorZ:i\d+>>,<<PhiZ1>>]     loop:<<HeaderY>>
-# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+## CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
+## CHECK-DAG:     <<PhiZ1:i\d+>> Phi [<<ArgZ>>,<<XorZ:i\d+>>,<<PhiZ1>>]     loop:<<HeaderY>>
+## CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
 #
-#                               ### Inner loop ###
-# CHECK-DAG:     <<PhiZ2:i\d+>> Phi [<<PhiZ1>>,<<XorZ>>]                   loop:<<HeaderZ:B\d+>>
-# CHECK-DAG:     <<XorZ>>       Xor [<<PhiZ2>>,<<Cst1>>]                   loop:<<HeaderZ>>
-# CHECK-DAG:     <<CondZ:z\d+>> Equal [<<XorZ>>,<<Cst0>>]                  loop:<<HeaderZ>>
-# CHECK-DAG:                    If [<<CondZ>>]                             loop:<<HeaderZ>>
+#                                ### Inner loop ###
+## CHECK-DAG:     <<PhiZ2:i\d+>> Phi [<<PhiZ1>>,<<XorZ>>]                   loop:<<HeaderZ:B\d+>>
+## CHECK-DAG:     <<XorZ>>       Xor [<<PhiZ2>>,<<Cst1>>]                   loop:<<HeaderZ>>
+## CHECK-DAG:     <<CondZ:z\d+>> Equal [<<XorZ>>,<<Cst0>>]                  loop:<<HeaderZ>>
+## CHECK-DAG:                    If [<<CondZ>>]                             loop:<<HeaderZ>>
 #
-# CHECK-DAG:     <<Add5>>       Add [<<PhiX>>,<<Cst5>>]                    loop:<<HeaderY>>
-# CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
-# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+## CHECK-DAG:     <<Add5>>       Add [<<PhiX>>,<<Cst5>>]                    loop:<<HeaderY>>
+## CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+## CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
 
-# CHECK-START: int TestCase.testInnerLoop(int, boolean, boolean) dead_code_elimination_final (after)
-# CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
-# CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
-# CHECK-DAG:     <<Cst0:i\d+>>  IntConstant 0
-# CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
-# CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
+## CHECK-START: int TestCase.testInnerLoop(int, boolean, boolean) dead_code_elimination_final (after)
+## CHECK-DAG:     <<ArgX:i\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgY:z\d+>>  ParameterValue
+## CHECK-DAG:     <<ArgZ:z\d+>>  ParameterValue
+## CHECK-DAG:     <<Cst0:i\d+>>  IntConstant 0
+## CHECK-DAG:     <<Cst1:i\d+>>  IntConstant 1
+## CHECK-DAG:     <<Cst7:i\d+>>  IntConstant 7
 #
-# CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add7:i\d+>>]               loop:<<HeaderY:B\d+>>
-# CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
-# CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
+## CHECK-DAG:     <<PhiX:i\d+>>  Phi [<<ArgX>>,<<Add7:i\d+>>]               loop:<<HeaderY:B\d+>>
+## CHECK-DAG:                    If [<<ArgY>>]                              loop:<<HeaderY>>
+## CHECK-DAG:     <<Add7>>       Add [<<PhiX>>,<<Cst7>>]                    loop:<<HeaderY>>
 #
-#                               ### Inner loop ###
-# CHECK-DAG:     <<PhiZ:i\d+>>  Phi [<<ArgZ>>,<<XorZ:i\d+>>]               loop:<<HeaderZ:B\d+>>
-# CHECK-DAG:     <<XorZ>>       Xor [<<PhiZ>>,<<Cst1>>]                    loop:<<HeaderZ>>
-# CHECK-DAG:     <<CondZ:z\d+>> Equal [<<XorZ>>,<<Cst0>>]                  loop:<<HeaderZ>>
-# CHECK-DAG:                    If [<<CondZ>>]                             loop:<<HeaderZ>>
+#                                ### Inner loop ###
+## CHECK-DAG:     <<PhiZ:i\d+>>  Phi [<<ArgZ>>,<<XorZ:i\d+>>]               loop:<<HeaderZ:B\d+>>
+## CHECK-DAG:     <<XorZ>>       Xor [<<PhiZ>>,<<Cst1>>]                    loop:<<HeaderZ>>
+## CHECK-DAG:     <<CondZ:z\d+>> Equal [<<XorZ>>,<<Cst0>>]                  loop:<<HeaderZ>>
+## CHECK-DAG:                    If [<<CondZ>>]                             loop:<<HeaderZ>>
 #
-# CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
+## CHECK-DAG:                    Return [<<PhiX>>]                          loop:none
 
 .method public static testInnerLoop(IZZ)I
   .registers 4
diff --git a/test/486-checker-must-do-null-check/src/Main.java b/test/486-checker-must-do-null-check/src/Main.java
index f285566..ea72718 100644
--- a/test/486-checker-must-do-null-check/src/Main.java
+++ b/test/486-checker-must-do-null-check/src/Main.java
@@ -15,8 +15,8 @@
  */
 
 public class Main {
-  // CHECK-START: void Main.InstanceOfPreChecked(java.lang.Object) instruction_simplifier (after)
-  // CHECK:       InstanceOf must_do_null_check:false
+  /// CHECK-START: void Main.InstanceOfPreChecked(java.lang.Object) instruction_simplifier (after)
+  /// CHECK:       InstanceOf must_do_null_check:false
   public void InstanceOfPreChecked(Object o) throws Exception {
     o.toString();
     if (o instanceof Main) {
@@ -24,23 +24,23 @@
     }
   }
 
-  // CHECK-START: void Main.InstanceOf(java.lang.Object) instruction_simplifier (after)
-  // CHECK:       InstanceOf must_do_null_check:true
+  /// CHECK-START: void Main.InstanceOf(java.lang.Object) instruction_simplifier (after)
+  /// CHECK:       InstanceOf must_do_null_check:true
   public void InstanceOf(Object o) throws Exception {
     if (o instanceof Main) {
       throw new Exception();
     }
   }
 
-  // CHECK-START: void Main.CheckCastPreChecked(java.lang.Object) instruction_simplifier (after)
-  // CHECK:       CheckCast must_do_null_check:false
+  /// CHECK-START: void Main.CheckCastPreChecked(java.lang.Object) instruction_simplifier (after)
+  /// CHECK:       CheckCast must_do_null_check:false
   public void CheckCastPreChecked(Object o) {
     o.toString();
     ((Main)o).Bar();
   }
 
-  // CHECK-START: void Main.CheckCast(java.lang.Object) instruction_simplifier (after)
-  // CHECK:       CheckCast must_do_null_check:true
+  /// CHECK-START: void Main.CheckCast(java.lang.Object) instruction_simplifier (after)
+  /// CHECK:       CheckCast must_do_null_check:true
   public void CheckCast(Object o) {
     ((Main)o).Bar();
   }
diff --git a/test/487-checker-inline-calls/expected.txt b/test/487-checker-inline-calls/expected.txt
new file mode 100644
index 0000000..2230482
--- /dev/null
+++ b/test/487-checker-inline-calls/expected.txt
@@ -0,0 +1,6 @@
+java.lang.Error
+	at Main.inline3(Main.java:48)
+	at Main.inline2(Main.java:44)
+	at Main.inline1(Main.java:40)
+	at Main.doTopCall(Main.java:36)
+	at Main.main(Main.java:21)
diff --git a/test/487-checker-inline-calls/info.txt b/test/487-checker-inline-calls/info.txt
new file mode 100644
index 0000000..9f5df8b
--- /dev/null
+++ b/test/487-checker-inline-calls/info.txt
@@ -0,0 +1 @@
+Checker test for ensuring inlining preserves stack traces.
diff --git a/test/487-checker-inline-calls/src/Main.java b/test/487-checker-inline-calls/src/Main.java
new file mode 100644
index 0000000..70384d5
--- /dev/null
+++ b/test/487-checker-inline-calls/src/Main.java
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+
+public class Main {
+  public static void main(String[] args) {
+    try {
+      doTopCall();
+    } catch (Error e) {
+      e.printStackTrace();
+    }
+  }
+
+  // We check that some inlining happened by checking the
+  // method index of the called method.
+
+  /// CHECK-START: void Main.doTopCall() inliner (before)
+  /// CHECK:     InvokeStaticOrDirect dex_file_index:2
+
+  /// CHECK-START: void Main.doTopCall() inliner (after)
+  /// CHECK:     InvokeStaticOrDirect dex_file_index:4
+  public static void doTopCall() {
+    inline1();
+  }
+
+  public static void inline1() {
+    inline2();
+  }
+
+  public static void inline2() {
+    inline3();
+  }
+
+  public static void inline3() {
+    throw new Error();
+  }
+}
diff --git a/test/488-checker-inline-recursive-calls/expected.txt b/test/488-checker-inline-recursive-calls/expected.txt
new file mode 100644
index 0000000..f615d3a
--- /dev/null
+++ b/test/488-checker-inline-recursive-calls/expected.txt
@@ -0,0 +1,7 @@
+java.lang.Error
+	at Main.inline3(Main.java:51)
+	at Main.doTopCall(Main.java:37)
+	at Main.inline2(Main.java:47)
+	at Main.inline1(Main.java:43)
+	at Main.doTopCall(Main.java:34)
+	at Main.main(Main.java:21)
diff --git a/test/488-checker-inline-recursive-calls/info.txt b/test/488-checker-inline-recursive-calls/info.txt
new file mode 100644
index 0000000..9abd93c
--- /dev/null
+++ b/test/488-checker-inline-recursive-calls/info.txt
@@ -0,0 +1 @@
+Checker test for inlining calls that in turn call the outer method.
diff --git a/test/488-checker-inline-recursive-calls/src/Main.java b/test/488-checker-inline-recursive-calls/src/Main.java
new file mode 100644
index 0000000..c1f25b3
--- /dev/null
+++ b/test/488-checker-inline-recursive-calls/src/Main.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+
+public class Main {
+  public static void main(String[] args) {
+    try {
+      doTopCall(true);
+    } catch (Error e) {
+      e.printStackTrace();
+    }
+  }
+
+  /// CHECK-START: void Main.doTopCall(boolean) inliner (before)
+  /// CHECK-NOT:   InvokeStaticOrDirect recursive:true
+
+  /// CHECK-START: void Main.doTopCall(boolean) inliner (after)
+  /// CHECK:       InvokeStaticOrDirect recursive:true
+  public static void doTopCall(boolean first_call) {
+    if (first_call) {
+      inline1();
+    } else {
+      while (true) {
+        inline3();
+      }
+    }
+  }
+
+  public static void inline1() {
+    inline2();
+  }
+
+  public static void inline2() {
+    doTopCall(false);
+  }
+
+  public static void inline3() {
+    throw new Error();
+  }
+}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index a3a639b..d224f43 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -32,11 +32,14 @@
 # an empty file touched in the intermediate directory.
 TEST_ART_RUN_TEST_BUILD_RULES :=
 
+# Dependencies for actually running a run-test.
+TEST_ART_RUN_TEST_DEPENDENCIES := $(DX) $(HOST_OUT_EXECUTABLES)/jasmin $(HOST_OUT_EXECUTABLES)/smali $(HOST_OUT_EXECUTABLES)/dexmerger
+
 # Helper to create individual build targets for tests. Must be called with $(eval).
 # $(1): the test number
 define define-build-art-run-test
   dmart_target := $(art_run_tests_dir)/art-run-tests/$(1)/touch
-$$(dmart_target): $(DX) $(HOST_OUT_EXECUTABLES)/jasmin $(HOST_OUT_EXECUTABLES)/smali $(HOST_OUT_EXECUTABLES)/dexmerger
+$$(dmart_target): $(TEST_ART_RUN_TEST_DEPENDENCIES)
 	$(hide) rm -rf $$(dir $$@) && mkdir -p $$(dir $$@)
 	$(hide) DX=$(abspath $(DX)) JASMIN=$(abspath $(HOST_OUT_EXECUTABLES)/jasmin) \
 	  SMALI=$(abspath $(HOST_OUT_EXECUTABLES)/smali) \
@@ -475,6 +478,19 @@
 
 TEST_ART_BROKEN_READ_BARRIER_RUN_TESTS :=
 
+# Tests that should fail in the heap poisoning configuration.
+# 137: Heap poisoning forces interpreter. Cannot run this with the interpreter.
+TEST_ART_BROKEN_HEAP_POISONING_RUN_TESTS := \
+  137-cfi
+
+ifeq ($(ART_HEAP_POISONING),true)
+  ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
+      $(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
+      $(IMAGE_TYPES),$(PICTEST_TYPES),$(DEBUGGABLE_TYPES),$(TEST_ART_BROKEN_HEAP_POISONING_RUN_TESTS),$(ALL_ADDRESS_SIZES))
+endif
+
+TEST_ART_BROKEN_HEAP_POISONING_RUN_TESTS :=
+
 # Test 137-cfi works in 32-bit only until we enable 64-bit ELF files.
 ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
     $(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
diff --git a/test/run-test b/test/run-test
index 12b743d..ed33099 100755
--- a/test/run-test
+++ b/test/run-test
@@ -75,7 +75,7 @@
 check_cmd="check"
 output="output.txt"
 build_output="build-output.txt"
-cfg_output="cfg-output.txt"
+cfg_output="graph.cfg"
 lib="libartd.so"
 run_args="--quiet"
 build_args=""
diff --git a/tools/art b/tools/art
index f167a73..2ee8940 100644
--- a/tools/art
+++ b/tools/art
@@ -97,7 +97,7 @@
     -XXlib:$LIBART \
     -Xnorelocate \
     -Ximage:$ANDROID_ROOT/framework/core.art \
-    -Xcompiler-option --include-debug-symbols \
+    -Xcompiler-option --generate-debug-info \
     "$@"
 
 EXIT_STATUS=$?
diff --git a/tools/buildbot-build.sh b/tools/buildbot-build.sh
new file mode 100755
index 0000000..77e6b1a
--- /dev/null
+++ b/tools/buildbot-build.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+#
+# 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.
+
+if [ ! -d art ]; then
+  echo "Script needs to be run at the root of the android tree"
+  exit 1
+fi
+
+common_targets="vogar vogar.jar core-tests apache-harmony-jdwp-tests-hostdex out/host/linux-x86/bin/adb jsr166-tests"
+android_root="/data/local/tmp/system"
+linker="linker"
+mode="target"
+j_arg="-j$(nproc)"
+make_command=
+
+if [[ "$TARGET_PRODUCT" == "armv8" ]]; then
+  linker="linker64"
+fi
+
+if [[ "$ART_TEST_ANDROID_ROOT" != "" ]]; then
+  android_root="$ART_TEST_ANDROID_ROOT"
+fi
+
+while true; do
+  if [[ "$1" == "--host" ]]; then
+    mode="host"
+    shift
+  elif [[ "$1" == "--target" ]]; then
+    mode="target"
+    shift
+  elif [[ "$1" == "--32" ]]; then
+    linker="linker"
+    shift
+  elif [[ "$1" == "--64" ]]; then
+    linker="linker64"
+    shift
+  elif [[ "$1" == "--android-root" ]]; then
+    shift
+    android_root=$1
+    shift
+  elif [[ "$1" == -j* ]]; then
+    j_arg=$1
+    shift
+  elif [[ "$1" == "" ]]; then
+    break
+  fi
+done
+
+if [[ $mode == "host" ]]; then
+  make_command="make $j_arg build-art-host-tests $common_targets"
+  echo "Executing $make_command"
+  $make_command
+elif [[ $mode == "target" ]]; then
+  # We need to provide our own linker in case the linker on the device
+  # is out of date.
+  env="TARGET_GLOBAL_LDFLAGS=-Wl,-dynamic-linker=$android_root/bin/$linker"
+  # Use '-e' to force the override of TARGET_GLOBAL_LDFLAGS.
+  # Also, we build extra tools that will be used by tests, so that
+  # they are compiled with our own linker.
+  make_command="make -e $j_arg build-art-target-tests $common_targets libjavacrypto linker toybox toolbox sh"
+  echo "Executing env $env $make_command"
+  env $env $make_command
+fi
+
diff --git a/tools/checker/file_format/checker/parser.py b/tools/checker/file_format/checker/parser.py
index 4eed391..33735cb 100644
--- a/tools/checker/file_format/checker/parser.py
+++ b/tools/checker/file_format/checker/parser.py
@@ -12,18 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from common.logger              import Logger
 from file_format.common         import SplitStream
 from file_format.checker.struct import CheckerFile, TestCase, TestAssertion, RegexExpression
 
 import re
 
+def __isCheckerLine(line):
+  return line.startswith("///") or line.startswith("##")
+
 def __extractLine(prefix, line):
   """ Attempts to parse a check line. The regex searches for a comment symbol
       followed by the CHECK keyword, given attribute and a colon at the very
       beginning of the line. Whitespaces are ignored.
   """
   rIgnoreWhitespace = r"\s*"
-  rCommentSymbols = [r"//", r"#"]
+  rCommentSymbols = [r"///", r"##"]
   regexPrefix = rIgnoreWhitespace + \
                 r"(" + r"|".join(rCommentSymbols) + r")" + \
                 rIgnoreWhitespace + \
@@ -37,13 +41,16 @@
   else:
     return None
 
-def __processLine(line, lineNo, prefix):
+def __processLine(line, lineNo, prefix, fileName):
   """ This function is invoked on each line of the check file and returns a pair
       which instructs the parser how the line should be handled. If the line is
       to be included in the current check group, it is returned in the first
       value. If the line starts a new check group, the name of the group is
       returned in the second value.
   """
+  if not __isCheckerLine(line):
+    return None, None
+
   # Lines beginning with 'CHECK-START' start a new test case.
   startLine = __extractLine(prefix + "-START", line)
   if startLine is not None:
@@ -69,8 +76,7 @@
   if notLine is not None:
     return (notLine, TestAssertion.Variant.Not, lineNo), None
 
-  # Other lines are ignored.
-  return None, None
+  Logger.fail("Checker assertion could not be parsed", fileName, lineNo)
 
 def __isMatchAtStart(match):
   """ Tests if the given Match occurred at the beginning of the line. """
@@ -137,9 +143,9 @@
 
 def ParseCheckerStream(fileName, prefix, stream):
   checkerFile = CheckerFile(fileName)
-  fnProcessLine = lambda line, lineNo: __processLine(line, lineNo, prefix)
+  fnProcessLine = lambda line, lineNo: __processLine(line, lineNo, prefix, fileName)
   fnLineOutsideChunk = lambda line, lineNo: \
-      Logger.fail("C1visualizer line not inside a group", fileName, lineNo)
+      Logger.fail("Checker line not inside a group", fileName, lineNo)
   for caseName, caseLines, startLineNo in SplitStream(stream, fnProcessLine, fnLineOutsideChunk):
     testCase = TestCase(checkerFile, caseName, startLineNo)
     for caseLine in caseLines:
diff --git a/tools/checker/file_format/checker/test.py b/tools/checker/file_format/checker/test.py
index 453deed..ff24cc1 100644
--- a/tools/checker/file_format/checker/test.py
+++ b/tools/checker/file_format/checker/test.py
@@ -26,43 +26,56 @@
 class CheckerParser_PrefixTest(unittest.TestCase):
 
   def tryParse(self, string):
-    checkerText = u"// CHECK-START: pass\n" + ToUnicode(string)
-    checkFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText))
+    checkerText = u"/// CHECK-START: pass\n" + ToUnicode(string)
+    return ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText))
+
+  def assertParses(self, string):
+    checkFile = self.tryParse(string)
     self.assertEqual(len(checkFile.testCases), 1)
-    testCase = checkFile.testCases[0]
-    return len(testCase.assertions) != 0
+    self.assertNotEqual(len(checkFile.testCases[0].assertions), 0)
+
+  def assertIgnored(self, string):
+    checkFile = self.tryParse(string)
+    self.assertEqual(len(checkFile.testCases), 1)
+    self.assertEqual(len(checkFile.testCases[0].assertions), 0)
+
+  def assertInvalid(self, string):
+    with self.assertRaises(CheckerException):
+      self.tryParse(string)
+
+  def test_ValidFormat(self):
+    self.assertParses("///CHECK:foo")
+    self.assertParses("##CHECK:bar")
 
   def test_InvalidFormat(self):
-    self.assertFalse(self.tryParse("CHECK"))
-    self.assertFalse(self.tryParse(":CHECK"))
-    self.assertFalse(self.tryParse("CHECK:"))
-    self.assertFalse(self.tryParse("//CHECK"))
-    self.assertFalse(self.tryParse("#CHECK"))
+    self.assertIgnored("CHECK")
+    self.assertIgnored(":CHECK")
+    self.assertIgnored("CHECK:")
+    self.assertIgnored("//CHECK")
+    self.assertIgnored("#CHECK")
+    self.assertInvalid("///CHECK")
+    self.assertInvalid("##CHECK")
 
-    self.assertTrue(self.tryParse("//CHECK:foo"))
-    self.assertTrue(self.tryParse("#CHECK:bar"))
-
-  def test_InvalidLabel(self):
-    self.assertFalse(self.tryParse("//ACHECK:foo"))
-    self.assertFalse(self.tryParse("#ACHECK:foo"))
+  def test_InvalidPrefix(self):
+    self.assertInvalid("///ACHECK:foo")
+    self.assertInvalid("##ACHECK:foo")
 
   def test_NotFirstOnTheLine(self):
-    self.assertFalse(self.tryParse("A// CHECK: foo"))
-    self.assertFalse(self.tryParse("A # CHECK: foo"))
-    self.assertFalse(self.tryParse("// // CHECK: foo"))
-    self.assertFalse(self.tryParse("# # CHECK: foo"))
+    self.assertIgnored("A/// CHECK: foo")
+    self.assertIgnored("A # CHECK: foo")
+    self.assertInvalid("/// /// CHECK: foo")
+    self.assertInvalid("## ## CHECK: foo")
 
   def test_WhitespaceAgnostic(self):
-    self.assertTrue(self.tryParse("  //CHECK: foo"))
-    self.assertTrue(self.tryParse("//  CHECK: foo"))
-    self.assertTrue(self.tryParse("    //CHECK: foo"))
-    self.assertTrue(self.tryParse("//    CHECK: foo"))
-
+    self.assertParses("  ///CHECK: foo")
+    self.assertParses("///  CHECK: foo")
+    self.assertParses("    ///CHECK: foo")
+    self.assertParses("///    CHECK: foo")
 
 class CheckerParser_RegexExpressionTest(unittest.TestCase):
 
   def parseAssertion(self, string, variant=""):
-    checkerText = u"// CHECK-START: pass\n// CHECK" + ToUnicode(variant) + u": " + ToUnicode(string)
+    checkerText = u"/// CHECK-START: pass\n/// CHECK" + ToUnicode(variant) + u": " + ToUnicode(string)
     checkerFile = ParseCheckerStream("<test-file>", "CHECK", io.StringIO(checkerText))
     self.assertEqual(len(checkerFile.testCases), 1)
     testCase = checkerFile.testCases[0]
@@ -204,9 +217,9 @@
   def test_SingleGroup(self):
     self.assertParsesTo(
       """
-        // CHECK-START: Example Group
-        // CHECK:  foo
-        // CHECK:    bar
+        /// CHECK-START: Example Group
+        /// CHECK:  foo
+        /// CHECK:    bar
       """,
       [ ( "Example Group", [ ("foo", TestAssertion.Variant.InOrder),
                              ("bar", TestAssertion.Variant.InOrder) ] ) ])
@@ -214,12 +227,12 @@
   def test_MultipleGroups(self):
     self.assertParsesTo(
       """
-        // CHECK-START: Example Group1
-        // CHECK: foo
-        // CHECK: bar
-        // CHECK-START: Example Group2
-        // CHECK: abc
-        // CHECK: def
+        /// CHECK-START: Example Group1
+        /// CHECK: foo
+        /// CHECK: bar
+        /// CHECK-START: Example Group2
+        /// CHECK: abc
+        /// CHECK: def
       """,
       [ ( "Example Group1", [ ("foo", TestAssertion.Variant.InOrder),
                               ("bar", TestAssertion.Variant.InOrder) ] ),
@@ -229,14 +242,14 @@
   def test_AssertionVariants(self):
     self.assertParsesTo(
       """
-        // CHECK-START: Example Group
-        // CHECK:      foo1
-        // CHECK:      foo2
-        // CHECK-NEXT: foo3
-        // CHECK-NEXT: foo4
-        // CHECK-NOT:  bar
-        // CHECK-DAG:  abc
-        // CHECK-DAG:  def
+        /// CHECK-START: Example Group
+        /// CHECK:      foo1
+        /// CHECK:      foo2
+        /// CHECK-NEXT: foo3
+        /// CHECK-NEXT: foo4
+        /// CHECK-NOT:  bar
+        /// CHECK-DAG:  abc
+        /// CHECK-DAG:  def
       """,
       [ ( "Example Group", [ ("foo1", TestAssertion.Variant.InOrder),
                              ("foo2", TestAssertion.Variant.InOrder),
@@ -250,20 +263,20 @@
     with self.assertRaises(CheckerException):
       self.parse(
         """
-          // CHECK-START: Example Group
-          // CHECK-DAG:  foo
-          // CHECK-NEXT: bar
+          /// CHECK-START: Example Group
+          /// CHECK-DAG:  foo
+          /// CHECK-NEXT: bar
         """)
     with self.assertRaises(CheckerException):
       self.parse(
         """
-          // CHECK-START: Example Group
-          // CHECK-NOT:  foo
-          // CHECK-NEXT: bar
+          /// CHECK-START: Example Group
+          /// CHECK-NOT:  foo
+          /// CHECK-NEXT: bar
         """)
     with self.assertRaises(CheckerException):
       self.parse(
         """
-          // CHECK-START: Example Group
-          // CHECK-NEXT: bar
+          /// CHECK-START: Example Group
+          /// CHECK-NEXT: bar
         """)
diff --git a/tools/checker/match/test.py b/tools/checker/match/test.py
index 348c1d2..ca748c7 100644
--- a/tools/checker/match/test.py
+++ b/tools/checker/match/test.py
@@ -105,7 +105,7 @@
   def assertMatches(self, checkerString, c1String):
     checkerString = \
       """
-        // CHECK-START: MyMethod MyPass
+        /// CHECK-START: MyMethod MyPass
       """ + checkerString
     c1String = \
       """
@@ -131,18 +131,18 @@
       self.assertMatches(checkerString, c1String)
 
   def test_Text(self):
-    self.assertMatches("// CHECK: foo bar", "foo bar")
-    self.assertDoesNotMatch("// CHECK: foo bar", "abc def")
+    self.assertMatches("/// CHECK: foo bar", "foo bar")
+    self.assertDoesNotMatch("/// CHECK: foo bar", "abc def")
 
   def test_Pattern(self):
-    self.assertMatches("// CHECK: abc {{de.}}", "abc de#")
-    self.assertDoesNotMatch("// CHECK: abc {{de.}}", "abc d#f")
+    self.assertMatches("/// CHECK: abc {{de.}}", "abc de#")
+    self.assertDoesNotMatch("/// CHECK: abc {{de.}}", "abc d#f")
 
   def test_Variables(self):
     self.assertMatches(
     """
-      // CHECK: foo<<X:.>>bar
-      // CHECK: abc<<X>>def
+      /// CHECK: foo<<X:.>>bar
+      /// CHECK: abc<<X>>def
     """,
     """
       foo0bar
@@ -150,9 +150,9 @@
     """)
     self.assertMatches(
     """
-      // CHECK: foo<<X:([0-9]+)>>bar
-      // CHECK: abc<<X>>def
-      // CHECK: ### <<X>> ###
+      /// CHECK: foo<<X:([0-9]+)>>bar
+      /// CHECK: abc<<X>>def
+      /// CHECK: ### <<X>> ###
     """,
     """
       foo1234bar
@@ -161,8 +161,8 @@
     """)
     self.assertDoesNotMatch(
     """
-      // CHECK: foo<<X:([0-9]+)>>bar
-      // CHECK: abc<<X>>def
+      /// CHECK: foo<<X:([0-9]+)>>bar
+      /// CHECK: abc<<X>>def
     """,
     """
       foo1234bar
@@ -170,16 +170,16 @@
     """)
 
   def test_WholeWordMustMatch(self):
-    self.assertMatches("// CHECK: b{{.}}r", "abc bar def")
-    self.assertDoesNotMatch("// CHECK: b{{.}}r", "abc Xbar def")
-    self.assertDoesNotMatch("// CHECK: b{{.}}r", "abc barX def")
-    self.assertDoesNotMatch("// CHECK: b{{.}}r", "abc b r def")
+    self.assertMatches("/// CHECK: b{{.}}r", "abc bar def")
+    self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc Xbar def")
+    self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc barX def")
+    self.assertDoesNotMatch("/// CHECK: b{{.}}r", "abc b r def")
 
   def test_InOrderAssertions(self):
     self.assertMatches(
     """
-      // CHECK: foo
-      // CHECK: bar
+      /// CHECK: foo
+      /// CHECK: bar
     """,
     """
       foo
@@ -187,8 +187,8 @@
     """)
     self.assertDoesNotMatch(
     """
-      // CHECK: foo
-      // CHECK: bar
+      /// CHECK: foo
+      /// CHECK: bar
     """,
     """
       bar
@@ -198,10 +198,10 @@
   def test_NextLineAssertions(self):
     self.assertMatches(
     """
-      // CHECK:      foo
-      // CHECK-NEXT: bar
-      // CHECK-NEXT: abc
-      // CHECK:      def
+      /// CHECK:      foo
+      /// CHECK-NEXT: bar
+      /// CHECK-NEXT: abc
+      /// CHECK:      def
     """,
     """
       foo
@@ -211,9 +211,9 @@
     """)
     self.assertMatches(
     """
-      // CHECK:      foo
-      // CHECK-NEXT: bar
-      // CHECK:      def
+      /// CHECK:      foo
+      /// CHECK-NEXT: bar
+      /// CHECK:      def
     """,
     """
       foo
@@ -223,8 +223,8 @@
     """)
     self.assertDoesNotMatch(
     """
-      // CHECK:      foo
-      // CHECK-NEXT: bar
+      /// CHECK:      foo
+      /// CHECK-NEXT: bar
     """,
     """
       foo
@@ -234,8 +234,8 @@
 
     self.assertDoesNotMatch(
     """
-      // CHECK:      foo
-      // CHECK-NEXT: bar
+      /// CHECK:      foo
+      /// CHECK-NEXT: bar
     """,
     """
       bar
@@ -246,8 +246,8 @@
   def test_DagAssertions(self):
     self.assertMatches(
     """
-      // CHECK-DAG: foo
-      // CHECK-DAG: bar
+      /// CHECK-DAG: foo
+      /// CHECK-DAG: bar
     """,
     """
       foo
@@ -255,8 +255,8 @@
     """)
     self.assertMatches(
     """
-      // CHECK-DAG: foo
-      // CHECK-DAG: bar
+      /// CHECK-DAG: foo
+      /// CHECK-DAG: bar
     """,
     """
       bar
@@ -266,10 +266,10 @@
   def test_DagAssertionsScope(self):
     self.assertMatches(
     """
-      // CHECK:     foo
-      // CHECK-DAG: abc
-      // CHECK-DAG: def
-      // CHECK:     bar
+      /// CHECK:     foo
+      /// CHECK-DAG: abc
+      /// CHECK-DAG: def
+      /// CHECK:     bar
     """,
     """
       foo
@@ -279,10 +279,10 @@
     """)
     self.assertDoesNotMatch(
     """
-      // CHECK:     foo
-      // CHECK-DAG: abc
-      // CHECK-DAG: def
-      // CHECK:     bar
+      /// CHECK:     foo
+      /// CHECK-DAG: abc
+      /// CHECK-DAG: def
+      /// CHECK:     bar
     """,
     """
       foo
@@ -292,10 +292,10 @@
     """)
     self.assertDoesNotMatch(
     """
-      // CHECK:     foo
-      // CHECK-DAG: abc
-      // CHECK-DAG: def
-      // CHECK:     bar
+      /// CHECK:     foo
+      /// CHECK-DAG: abc
+      /// CHECK-DAG: def
+      /// CHECK:     bar
     """,
     """
       foo
@@ -307,7 +307,7 @@
   def test_NotAssertions(self):
     self.assertMatches(
     """
-      // CHECK-NOT: foo
+      /// CHECK-NOT: foo
     """,
     """
       abc
@@ -315,7 +315,7 @@
     """)
     self.assertDoesNotMatch(
     """
-      // CHECK-NOT: foo
+      /// CHECK-NOT: foo
     """,
     """
       abc foo
@@ -323,8 +323,8 @@
     """)
     self.assertDoesNotMatch(
     """
-      // CHECK-NOT: foo
-      // CHECK-NOT: bar
+      /// CHECK-NOT: foo
+      /// CHECK-NOT: bar
     """,
     """
       abc
@@ -334,9 +334,9 @@
   def test_NotAssertionsScope(self):
     self.assertMatches(
     """
-      // CHECK:     abc
-      // CHECK-NOT: foo
-      // CHECK:     def
+      /// CHECK:     abc
+      /// CHECK-NOT: foo
+      /// CHECK:     def
     """,
     """
       abc
@@ -344,9 +344,9 @@
     """)
     self.assertMatches(
     """
-      // CHECK:     abc
-      // CHECK-NOT: foo
-      // CHECK:     def
+      /// CHECK:     abc
+      /// CHECK-NOT: foo
+      /// CHECK:     def
     """,
     """
       abc
@@ -355,9 +355,9 @@
     """)
     self.assertDoesNotMatch(
     """
-      // CHECK:     abc
-      // CHECK-NOT: foo
-      // CHECK:     def
+      /// CHECK:     abc
+      /// CHECK-NOT: foo
+      /// CHECK:     def
     """,
     """
       abc
@@ -368,8 +368,8 @@
   def test_LineOnlyMatchesOnce(self):
     self.assertMatches(
     """
-      // CHECK-DAG: foo
-      // CHECK-DAG: foo
+      /// CHECK-DAG: foo
+      /// CHECK-DAG: foo
     """,
     """
       foo
@@ -378,8 +378,8 @@
     """)
     self.assertDoesNotMatch(
     """
-      // CHECK-DAG: foo
-      // CHECK-DAG: foo
+      /// CHECK-DAG: foo
+      /// CHECK-DAG: foo
     """,
     """
       foo
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index a8bc4e1..b053f0d 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -21,28 +21,35 @@
   name: "libcore.java.lang.SystemTest#testSystemProperties_mutable"
 },
 {
-  description: "Differences between vogar and cts",
+  description: "Differences between vogar and cts. Passes with --mode activity",
   result: EXEC_FAILED,
   modes: [device],
-  names: ["libcore.java.lang.OldSystemTest#test_getProperties",
-          "org.apache.harmony.tests.java.lang.Process2Test#test_getErrorStream",
-          "org.apache.harmony.tests.java.lang.ProcessTest#test_exitValue"]
+  names: ["libcore.java.lang.OldSystemTest#test_getProperties"]
 },
 {
-  description: "Failures needing investigation",
+  description: "Differences between vogar and cts. EACCESS when run with vogar.
+                Passes on host, passes with cts. Passes with vogar with su
+                (--invoke-with \"su root\"). Does not pass after setting chmod
+                777 all directories on path to socket (on device without su).",
+  result: EXEC_FAILED,
+  modes: [device],
+  names: ["libcore.io.OsTest#testUnixDomainSockets_in_file_system"]
+},
+{
+  description: "Issue with incorrect device time (1970)",
   result: EXEC_FAILED,
   modes: [device],
   names: ["libcore.java.util.TimeZoneTest#testDisplayNames",
           "libcore.java.util.TimeZoneTest#test_useDaylightTime_Taiwan",
-          "libcore.java.util.TimeZoneTest#testAllDisplayNames",
-          "libcore.io.OsTest#testUnixDomainSockets_in_file_system",
-          "org.apache.harmony.luni.tests.java.net.URLConnectionTest#test_setReadTimeoutI",
-          "org.apache.harmony.tests.java.util.DateTest#test_Constructor",
-          "org.apache.harmony.tests.java.util.ScannerTest#test_Constructor_LReadableByteChannel",
-          "org.apache.harmony.tests.java.util.TimeZoneTest#test_hasSameRules_Ljava_util_TimeZone",
-          "org.apache.harmony.tests.java.text.ChoiceFormatTest#testEscapedPatternWithConsecutiveQuotes",
-          "org.apache.harmony.tests.java.text.ChoiceFormatTest#testToPatternWithInfinities",
-          "org.apache.harmony.tests.java.text.MessageFormatTest#test19011159"]
+          "org.apache.harmony.tests.java.util.TimeZoneTest#test_hasSameRules_Ljava_util_TimeZone"],
+  bug: 20879084
+},
+{
+  description: "Issue with incorrect device time (1970). Test assumes that DateTime.now()
+                is greater then a date in 1998.",
+  result: EXEC_FAILED,
+  modes: [device],
+  names: ["org.apache.harmony.tests.java.util.DateTest#test_Constructor"]
 },
 {
   description: "Failing due to a locale problem on hammerhead.",
@@ -74,7 +81,8 @@
           "libcore.net.NetworkSecurityPolicyTest#testCleartextTrafficPolicyWithJarHttpURLConnection",
           "org.apache.harmony.luni.tests.internal.net.www.protocol.http.HttpURLConnectionTest",
           "org.apache.harmony.luni.tests.internal.net.www.protocol.https.HttpsURLConnectionTest",
-          "org.apache.harmony.luni.tests.java.net.URLConnectionTest"
+          "org.apache.harmony.luni.tests.java.net.URLConnectionTest",
+          "org.apache.harmony.tests.java.util.ScannerTest#test_Constructor_LReadableByteChannel"
          ]
 },
 {