Merge "ARM64: Use macros for increasing and decreasing frame size."
diff --git a/Android.bp b/Android.bp
index 835048d..77b9ac3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,6 +1,34 @@
+// TODO: These should be handled with transitive static library dependencies
+art_static_dependencies = [
+    // Note: the order is important because of static linking resolution.
+    "libziparchive",
+    "libnativehelper",
+    "libnativebridge",
+    "libnativeloader",
+    "libsigchain_dummy",
+    "liblog",
+    "libz",
+    "libbacktrace",
+    "libcutils",
+    "libunwindbacktrace",
+    "libutils",
+    "libbase",
+    "liblz4",
+    "liblzma",
+]
+
 subdirs = [
+    "benchmark",
     "build",
     "compiler",
+    "dalvikvm",
+    "dexdump",
+    "dexlayout",
+    "dexlist",
+    "disassembler",
+    "oatdump",
     "runtime",
     "sigchainlib",
+    "tools/cpp-define-generator",
+    "tools/dmtracedump",
 ]
diff --git a/Android.mk b/Android.mk
index 4ea169a..0ed5d87 100644
--- a/Android.mk
+++ b/Android.mk
@@ -76,20 +76,13 @@
 ########################################################################
 # product rules
 
-include $(art_path)/dexdump/Android.mk
-include $(art_path)/dexlayout/Android.mk
-include $(art_path)/dexlist/Android.mk
 include $(art_path)/dex2oat/Android.mk
-include $(art_path)/disassembler/Android.mk
-include $(art_path)/oatdump/Android.mk
 include $(art_path)/imgdiag/Android.mk
 include $(art_path)/patchoat/Android.mk
 include $(art_path)/profman/Android.mk
-include $(art_path)/dalvikvm/Android.mk
 include $(art_path)/tools/Android.mk
 include $(art_path)/tools/ahat/Android.mk
 include $(art_path)/tools/dexfuzz/Android.mk
-include $(art_path)/tools/dmtracedump/Android.mk
 include $(art_path)/libart_fake/Android.mk
 
 
@@ -114,7 +107,6 @@
 include $(art_path)/build/Android.common_test.mk
 include $(art_path)/build/Android.gtest.mk
 include $(art_path)/test/Android.run-test.mk
-include $(art_path)/benchmark/Android.mk
 
 TEST_ART_ADB_ROOT_AND_REMOUNT := \
     (adb root && \
diff --git a/benchmark/Android.bp b/benchmark/Android.bp
new file mode 100644
index 0000000..617f5b0
--- /dev/null
+++ b/benchmark/Android.bp
@@ -0,0 +1,43 @@
+//
+// 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.
+//
+
+art_cc_library {
+    name: "libartbenchmark",
+    host_supported: true,
+    defaults: ["art_defaults", "art_debug_defaults"],
+    srcs: [
+        "jobject-benchmark/jobject_benchmark.cc",
+        "jni-perf/perf_jni.cc",
+        "scoped-primitive-array/scoped_primitive_array.cc",
+    ],
+    shared_libs: [
+        "libart",
+        "libbacktrace",
+        "libnativehelper",
+    ],
+    clang: true,
+    target: {
+        android: {
+            shared_libs: ["libdl"],
+        },
+        host: {
+            host_ldlibs: ["-ldl", "-lpthread"],
+        },
+    },
+    cflags: [
+        "-Wno-frame-larger-than=",
+    ],
+}
diff --git a/benchmark/Android.mk b/benchmark/Android.mk
deleted file mode 100644
index 2360bcc..0000000
--- a/benchmark/Android.mk
+++ /dev/null
@@ -1,79 +0,0 @@
-#
-# 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include art/build/Android.common_build.mk
-
-LIBARTBENCHMARK_COMMON_SRC_FILES := \
-  jobject-benchmark/jobject_benchmark.cc \
-  jni-perf/perf_jni.cc \
-  scoped-primitive-array/scoped_primitive_array.cc
-
-# $(1): target or host
-define build-libartbenchmark
-  ifneq ($(1),target)
-    ifneq ($(1),host)
-      $$(error expected target or host for argument 1, received $(1))
-    endif
-  endif
-
-  art_target_or_host := $(1)
-
-  include $(CLEAR_VARS)
-  LOCAL_CPP_EXTENSION := $(ART_CPP_EXTENSION)
-  LOCAL_MODULE := libartbenchmark
-  ifeq ($$(art_target_or_host),target)
-    LOCAL_MODULE_TAGS := tests
-  endif
-  LOCAL_SRC_FILES := $(LIBARTBENCHMARK_COMMON_SRC_FILES)
-  LOCAL_SHARED_LIBRARIES += libart libbacktrace libnativehelper
-  LOCAL_C_INCLUDES += $(ART_C_INCLUDES) art/runtime
-  LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
-  LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
-  ifeq ($$(art_target_or_host),target)
-    LOCAL_CLANG := $(ART_TARGET_CLANG)
-    $(call set-target-local-cflags-vars,debug)
-    LOCAL_SHARED_LIBRARIES += libdl
-    LOCAL_MULTILIB := both
-    # LOCAL_MODULE_PATH_32 := $(ART_TARGET_OUT)/$(ART_TARGET_ARCH_32)
-    # LOCAL_MODULE_PATH_64 := $(ART_TARGET_OUT)/$(ART_TARGET_ARCH_64)
-    LOCAL_MODULE_TARGET_ARCH := $(ART_SUPPORTED_ARCH)
-    include $(BUILD_SHARED_LIBRARY)
-  else # host
-    LOCAL_CLANG := $(ART_HOST_CLANG)
-    LOCAL_CFLAGS := $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
-    LOCAL_ASFLAGS := $(ART_HOST_ASFLAGS) $(ART_HOST_DEBUG_ASFLAGS)
-    LOCAL_LDLIBS := -ldl -lpthread
-    LOCAL_IS_HOST_MODULE := true
-    LOCAL_MULTILIB := both
-    include $(BUILD_HOST_SHARED_LIBRARY)
-  endif
-
-  # Clear locally used variables.
-  art_target_or_host :=
-endef
-
-ifeq ($(ART_BUILD_TARGET),true)
-  $(eval $(call build-libartbenchmark,target))
-endif
-ifeq ($(ART_BUILD_HOST),true)
-  $(eval $(call build-libartbenchmark,host))
-endif
-
-# Clear locally used variables.
-LOCAL_PATH :=
-LIBARTBENCHMARK_COMMON_SRC_FILES :=
diff --git a/build/Android.bp b/build/Android.bp
index ed9f308..630cf3c 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -101,6 +101,9 @@
                 // Apple, it's a pain.
                 "-Wmissing-noreturn",
             ],
+            host_ldlibs: [
+                "-lrt",
+            ],
         },
         host: {
             cflags: [
@@ -108,6 +111,10 @@
                 // clang/libunwind bugs that cause SEGVs in run-test-004-ThreadStress.
                 "-fno-omit-frame-pointer",
             ],
+            host_ldlibs: [
+                "-ldl",
+                "-lpthread",
+            ],
         },
     },
 
diff --git a/build/Android.common_path.mk b/build/Android.common_path.mk
index 3f25ae1..e88d027 100644
--- a/build/Android.common_path.mk
+++ b/build/Android.common_path.mk
@@ -123,7 +123,7 @@
 
 # Depend on the -target or -host phony targets generated by the build system
 # for each module
-ART_TARGET_EXECUTABLES :=
+ART_TARGET_EXECUTABLES := dalvikvm-target
 ifneq ($(ART_BUILD_TARGET_NDEBUG),false)
 ART_TARGET_EXECUTABLES += $(foreach name,$(ART_CORE_EXECUTABLES),$(name)-target)
 endif
@@ -131,7 +131,7 @@
 ART_TARGET_EXECUTABLES += $(foreach name,$(ART_CORE_EXECUTABLES),$(name)d-target)
 endif
 
-ART_HOST_EXECUTABLES :=
+ART_HOST_EXECUTABLES := dalvikvm-host
 ifneq ($(ART_BUILD_HOST_NDEBUG),false)
 ART_HOST_EXECUTABLES += $(foreach name,$(ART_CORE_EXECUTABLES),$(name)-host)
 endif
diff --git a/build/art.go b/build/art.go
index d41b407..9cab3b9 100644
--- a/build/art.go
+++ b/build/art.go
@@ -137,7 +137,26 @@
 	p.Target.Android.Cflags = deviceFlags(ctx)
 	p.Target.Host.Cflags = hostFlags(ctx)
 	ctx.AppendProperties(p)
+}
 
+type artGlobalDefaults struct{}
+
+func (a *artCustomLinkerCustomizer) CustomizeProperties(ctx android.CustomizePropertiesContext) {
+	linker := envDefault(ctx, "CUSTOM_TARGET_LINKER", "")
+	if linker != "" {
+		type props struct {
+			DynamicLinker string
+		}
+
+		p := &props{}
+		p.DynamicLinker = linker
+		ctx.AppendProperties(p)
+	}
+}
+
+type artCustomLinkerCustomizer struct{}
+
+func (a *artPrefer32BitCustomizer) CustomizeProperties(ctx android.CustomizePropertiesContext) {
 	if envTrue(ctx, "HOST_PREFER_32_BIT") {
 		type props struct {
 			Target struct {
@@ -153,22 +172,7 @@
 	}
 }
 
-type artGlobalDefaults struct{}
-
-func (a *artLinkerCustomizer) CustomizeProperties(ctx android.CustomizePropertiesContext) {
-	linker := envDefault(ctx, "CUSTOM_TARGET_LINKER", "")
-	if linker != "" {
-		type props struct {
-			DynamicLinker string
-		}
-
-		p := &props{}
-		p.DynamicLinker = linker
-		ctx.AppendProperties(p)
-	}
-}
-
-type artLinkerCustomizer struct{}
+type artPrefer32BitCustomizer struct{}
 
 func init() {
 	soong.RegisterModuleType("art_cc_library", artLibrary)
@@ -200,6 +204,7 @@
 	c := &codegenCustomizer{}
 	android.AddCustomizer(library, c)
 	props = append(props, &c.codegenProperties)
+
 	return module, props
 }
 
@@ -207,7 +212,8 @@
 	binary, _ := cc.NewBinary(android.HostAndDeviceSupported)
 	module, props := binary.Init()
 
-	android.AddCustomizer(binary, &artLinkerCustomizer{})
+	android.AddCustomizer(binary, &artCustomLinkerCustomizer{})
+	android.AddCustomizer(binary, &artPrefer32BitCustomizer{})
 	return module, props
 }
 
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 0143268..595a824 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -188,6 +188,7 @@
         "liblzma",
     ],
     include_dirs: ["art/disassembler"],
+    export_include_dirs: ["."],
 }
 
 gensrcs {
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 5301a6b..3c4a3e8 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -4598,7 +4598,6 @@
   }
   if (needs_write_barrier) {
     // Temporary registers for the write barrier.
-    // These registers may be used for Baker read barriers too.
     locations->AddTemp(Location::RequiresRegister());  // Possibly used for ref. poisoning too.
     locations->AddTemp(Location::RequiresRegister());
   }
@@ -4716,127 +4715,42 @@
           __ Bind(&non_zero);
         }
 
-        if (kEmitCompilerReadBarrier) {
-          if (!kUseBakerReadBarrier) {
-            // When (non-Baker) read barriers are enabled, the type
-            // checking instrumentation requires two read barriers
-            // generated by CodeGeneratorARM::GenerateReadBarrierSlow:
-            //
-            //   __ Mov(temp2, temp1);
-            //   // /* HeapReference<Class> */ temp1 = temp1->component_type_
-            //   __ LoadFromOffset(kLoadWord, temp1, temp1, component_offset);
-            //   codegen_->GenerateReadBarrierSlow(
-            //       instruction, temp1_loc, temp1_loc, temp2_loc, component_offset);
-            //
-            //   // /* HeapReference<Class> */ temp2 = value->klass_
-            //   __ LoadFromOffset(kLoadWord, temp2, value, class_offset);
-            //   codegen_->GenerateReadBarrierSlow(
-            //       instruction, temp2_loc, temp2_loc, value_loc, class_offset, temp1_loc);
-            //
-            //   __ cmp(temp1, ShifterOperand(temp2));
-            //
-            // However, the second read barrier may trash `temp`, as it
-            // is a temporary register, and as such would not be saved
-            // along with live registers before calling the runtime (nor
-            // restored afterwards).  So in this case, we bail out and
-            // delegate the work to the array set slow path.
-            //
-            // TODO: Extend the register allocator to support a new
-            // "(locally) live temp" location so as to avoid always
-            // going into the slow path when read barriers are enabled?
-            //
-            // There is no such problem with Baker read barriers (see below).
-            __ b(slow_path->GetEntryLabel());
-          } else {
-            Register temp3 = IP;
-            Location temp3_loc = Location::RegisterLocation(temp3);
+        // Note that when read barriers are enabled, the type checks
+        // are performed without read barriers.  This is fine, even in
+        // the case where a class object is in the from-space after
+        // the flip, as a comparison involving such a type would not
+        // produce a false positive; it may of course produce a false
+        // negative, in which case we would take the ArraySet slow
+        // path.
 
-            // Note: `temp3` (scratch register IP) cannot be used as
-            // `ref` argument of GenerateFieldLoadWithBakerReadBarrier
-            // calls below (see ReadBarrierMarkSlowPathARM for more
-            // details).
+        // /* HeapReference<Class> */ temp1 = array->klass_
+        __ LoadFromOffset(kLoadWord, temp1, array, class_offset);
+        codegen_->MaybeRecordImplicitNullCheck(instruction);
+        __ MaybeUnpoisonHeapReference(temp1);
 
-            // /* HeapReference<Class> */ temp1 = array->klass_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction,
-                                                            temp1_loc,
-                                                            array,
-                                                            class_offset,
-                                                            temp3_loc,
-                                                            /* needs_null_check */ true);
+        // /* HeapReference<Class> */ temp1 = temp1->component_type_
+        __ LoadFromOffset(kLoadWord, temp1, temp1, component_offset);
+        // /* HeapReference<Class> */ temp2 = value->klass_
+        __ LoadFromOffset(kLoadWord, temp2, value, class_offset);
+        // If heap poisoning is enabled, no need to unpoison `temp1`
+        // nor `temp2`, as we are comparing two poisoned references.
+        __ cmp(temp1, ShifterOperand(temp2));
 
-            // /* HeapReference<Class> */ temp1 = temp1->component_type_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction,
-                                                            temp1_loc,
-                                                            temp1,
-                                                            component_offset,
-                                                            temp3_loc,
-                                                            /* needs_null_check */ false);
-            // Register `temp1` is not trashed by the read barrier
-            // emitted by GenerateFieldLoadWithBakerReadBarrier below,
-            // as that method produces a call to a ReadBarrierMarkRegX
-            // entry point, which saves all potentially live registers,
-            // including temporaries such a `temp1`.
-            // /* HeapReference<Class> */ temp2 = value->klass_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction,
-                                                            temp2_loc,
-                                                            value,
-                                                            class_offset,
-                                                            temp3_loc,
-                                                            /* needs_null_check */ false);
-            // If heap poisoning is enabled, `temp1` and `temp2` have
-            // been unpoisoned by the the previous calls to
-            // CodeGeneratorARM::GenerateFieldLoadWithBakerReadBarrier.
-            __ cmp(temp1, ShifterOperand(temp2));
-
-            if (instruction->StaticTypeOfArrayIsObjectArray()) {
-              Label do_put;
-              __ b(&do_put, EQ);
-              // We do not need to emit a read barrier for the
-              // following heap reference load, as `temp1` is only used
-              // in a comparison with null below, and this reference
-              // is not kept afterwards.
-              // /* HeapReference<Class> */ temp1 = temp1->super_class_
-              __ LoadFromOffset(kLoadWord, temp1, temp1, super_offset);
-              // If heap poisoning is enabled, no need to unpoison
-              // `temp`, as we are comparing against null below.
-              __ CompareAndBranchIfNonZero(temp1, slow_path->GetEntryLabel());
-              __ Bind(&do_put);
-            } else {
-              __ b(slow_path->GetEntryLabel(), NE);
-            }
-          }
-        } else {
-          // Non read barrier code.
-
-          // /* HeapReference<Class> */ temp1 = array->klass_
-          __ LoadFromOffset(kLoadWord, temp1, array, class_offset);
-          codegen_->MaybeRecordImplicitNullCheck(instruction);
+        if (instruction->StaticTypeOfArrayIsObjectArray()) {
+          Label do_put;
+          __ b(&do_put, EQ);
+          // If heap poisoning is enabled, the `temp1` reference has
+          // not been unpoisoned yet; unpoison it now.
           __ MaybeUnpoisonHeapReference(temp1);
 
-          // /* HeapReference<Class> */ temp1 = temp1->component_type_
-          __ LoadFromOffset(kLoadWord, temp1, temp1, component_offset);
-          // /* HeapReference<Class> */ temp2 = value->klass_
-          __ LoadFromOffset(kLoadWord, temp2, value, class_offset);
-          // If heap poisoning is enabled, no need to unpoison `temp1`
-          // nor `temp2`, as we are comparing two poisoned references.
-          __ cmp(temp1, ShifterOperand(temp2));
-
-          if (instruction->StaticTypeOfArrayIsObjectArray()) {
-            Label do_put;
-            __ b(&do_put, EQ);
-            // If heap poisoning is enabled, the `temp1` reference has
-            // not been unpoisoned yet; unpoison it now.
-            __ MaybeUnpoisonHeapReference(temp1);
-
-            // /* HeapReference<Class> */ temp1 = temp1->super_class_
-            __ LoadFromOffset(kLoadWord, temp1, temp1, super_offset);
-            // If heap poisoning is enabled, no need to unpoison
-            // `temp1`, as we are comparing against null below.
-            __ CompareAndBranchIfNonZero(temp1, slow_path->GetEntryLabel());
-            __ Bind(&do_put);
-          } else {
-            __ b(slow_path->GetEntryLabel(), NE);
-          }
+          // /* HeapReference<Class> */ temp1 = temp1->super_class_
+          __ LoadFromOffset(kLoadWord, temp1, temp1, super_offset);
+          // If heap poisoning is enabled, no need to unpoison
+          // `temp1`, as we are comparing against null below.
+          __ CompareAndBranchIfNonZero(temp1, slow_path->GetEntryLabel());
+          __ Bind(&do_put);
+        } else {
+          __ b(slow_path->GetEntryLabel(), NE);
         }
       }
 
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 36f7b4d..1d2f334 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -336,36 +336,6 @@
   DISALLOW_COPY_AND_ASSIGN(LoadClassSlowPathARM64);
 };
 
-class LoadStringSlowPathARM64 : public SlowPathCodeARM64 {
- public:
-  explicit LoadStringSlowPathARM64(HLoadString* instruction) : SlowPathCodeARM64(instruction) {}
-
-  void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
-    LocationSummary* locations = instruction_->GetLocations();
-    DCHECK(!locations->GetLiveRegisters()->ContainsCoreRegister(locations->Out().reg()));
-    CodeGeneratorARM64* arm64_codegen = down_cast<CodeGeneratorARM64*>(codegen);
-
-    __ Bind(GetEntryLabel());
-    SaveLiveRegisters(codegen, locations);
-
-    InvokeRuntimeCallingConvention calling_convention;
-    const uint32_t string_index = instruction_->AsLoadString()->GetStringIndex();
-    __ Mov(calling_convention.GetRegisterAt(0).W(), string_index);
-    arm64_codegen->InvokeRuntime(kQuickResolveString, instruction_, instruction_->GetDexPc(), this);
-    CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
-    Primitive::Type type = instruction_->GetType();
-    arm64_codegen->MoveLocation(locations->Out(), calling_convention.GetReturnLocation(type), type);
-
-    RestoreLiveRegisters(codegen, locations);
-    __ B(GetExitLabel());
-  }
-
-  const char* GetDescription() const OVERRIDE { return "LoadStringSlowPathARM64"; }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LoadStringSlowPathARM64);
-};
-
 class NullCheckSlowPathARM64 : public SlowPathCodeARM64 {
  public:
   explicit NullCheckSlowPathARM64(HNullCheck* instr) : SlowPathCodeARM64(instr) {}
@@ -2178,11 +2148,6 @@
   } else {
     locations->SetInAt(2, Location::RequiresRegister());
   }
-  if (kEmitCompilerReadBarrier && kUseBakerReadBarrier && (value_type == Primitive::kPrimNot)) {
-    // Additional temporary registers for a Baker read barrier.
-    locations->AddTemp(Location::RequiresRegister());
-    locations->AddTemp(Location::RequiresRegister());
-  }
 }
 
 void InstructionCodeGeneratorARM64::VisitArraySet(HArraySet* instruction) {
@@ -2269,144 +2234,44 @@
           __ Bind(&non_zero);
         }
 
-        if (kEmitCompilerReadBarrier) {
-          if (!kUseBakerReadBarrier) {
-            // When (non-Baker) read barriers are enabled, the type
-            // checking instrumentation requires two read barriers
-            // generated by CodeGeneratorARM64::GenerateReadBarrierSlow:
-            //
-            //   __ Mov(temp2, temp);
-            //   // /* HeapReference<Class> */ temp = temp->component_type_
-            //   __ Ldr(temp, HeapOperand(temp, component_offset));
-            //   codegen_->GenerateReadBarrierSlow(
-            //       instruction, temp_loc, temp_loc, temp2_loc, component_offset);
-            //
-            //   // /* HeapReference<Class> */ temp2 = value->klass_
-            //   __ Ldr(temp2, HeapOperand(Register(value), class_offset));
-            //   codegen_->GenerateReadBarrierSlow(
-            //       instruction, temp2_loc, temp2_loc, value_loc, class_offset, temp_loc);
-            //
-            //   __ Cmp(temp, temp2);
-            //
-            // However, the second read barrier may trash `temp`, as it
-            // is a temporary register, and as such would not be saved
-            // along with live registers before calling the runtime (nor
-            // restored afterwards).  So in this case, we bail out and
-            // delegate the work to the array set slow path.
-            //
-            // TODO: Extend the register allocator to support a new
-            // "(locally) live temp" location so as to avoid always
-            // going into the slow path when read barriers are enabled?
-            //
-            // There is no such problem with Baker read barriers (see below).
-            __ B(slow_path->GetEntryLabel());
-          } else {
-            // Note that we cannot use `temps` (instance of VIXL's
-            // UseScratchRegisterScope) to allocate `temp2` because
-            // the Baker read barriers generated by
-            // GenerateFieldLoadWithBakerReadBarrier below also use
-            // that facility to allocate a temporary register, thus
-            // making VIXL's scratch register pool empty.
-            Location temp2_loc = locations->GetTemp(0);
-            Register temp2 = WRegisterFrom(temp2_loc);
+        // Note that when Baker read barriers are enabled, the type
+        // checks are performed without read barriers.  This is fine,
+        // even in the case where a class object is in the from-space
+        // after the flip, as a comparison involving such a type would
+        // not produce a false positive; it may of course produce a
+        // false negative, in which case we would take the ArraySet
+        // slow path.
 
-            // Note: Because it is acquired from VIXL's scratch register
-            // pool, `temp` might be IP0, and thus cannot be used as
-            // `ref` argument of GenerateFieldLoadWithBakerReadBarrier
-            // calls below (see ReadBarrierMarkSlowPathARM64 for more
-            // details).
+        Register temp2 = temps.AcquireSameSizeAs(array);
+        // /* HeapReference<Class> */ temp = array->klass_
+        __ Ldr(temp, HeapOperand(array, class_offset));
+        codegen_->MaybeRecordImplicitNullCheck(instruction);
+        GetAssembler()->MaybeUnpoisonHeapReference(temp);
 
-            // /* HeapReference<Class> */ temp2 = array->klass_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction,
-                                                            temp2_loc,
-                                                            array,
-                                                            class_offset,
-                                                            temp,
-                                                            /* needs_null_check */ true,
-                                                            /* use_load_acquire */ false);
+        // /* HeapReference<Class> */ temp = temp->component_type_
+        __ Ldr(temp, HeapOperand(temp, component_offset));
+        // /* HeapReference<Class> */ temp2 = value->klass_
+        __ Ldr(temp2, HeapOperand(Register(value), class_offset));
+        // If heap poisoning is enabled, no need to unpoison `temp`
+        // nor `temp2`, as we are comparing two poisoned references.
+        __ Cmp(temp, temp2);
+        temps.Release(temp2);
 
-            // /* HeapReference<Class> */ temp2 = temp2->component_type_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction,
-                                                            temp2_loc,
-                                                            temp2,
-                                                            component_offset,
-                                                            temp,
-                                                            /* needs_null_check */ false,
-                                                            /* use_load_acquire */ false);
-            // For the same reason that we request `temp2` from the
-            // register allocator above, we cannot get `temp3` from
-            // VIXL's scratch register pool.
-            Location temp3_loc = locations->GetTemp(1);
-            Register temp3 = WRegisterFrom(temp3_loc);
-            // Register `temp2` is not trashed by the read barrier
-            // emitted by GenerateFieldLoadWithBakerReadBarrier below,
-            // as that method produces a call to a ReadBarrierMarkRegX
-            // entry point, which saves all potentially live registers,
-            // including temporaries such a `temp2`.
-            // /* HeapReference<Class> */ temp3 = register_value->klass_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(instruction,
-                                                            temp3_loc,
-                                                            value.W(),
-                                                            class_offset,
-                                                            temp,
-                                                            /* needs_null_check */ false,
-                                                            /* use_load_acquire */ false);
-            // If heap poisoning is enabled, `temp2` and `temp3` have
-            // been unpoisoned by the the previous calls to
-            // CodeGeneratorARM64::GenerateFieldLoadWithBakerReadBarrier.
-            __ Cmp(temp2, temp3);
-
-            if (instruction->StaticTypeOfArrayIsObjectArray()) {
-              vixl::aarch64::Label do_put;
-              __ B(eq, &do_put);
-              // We do not need to emit a read barrier for the
-              // following heap reference load, as `temp2` is only used
-              // in a comparison with null below, and this reference
-              // is not kept afterwards.
-              // /* HeapReference<Class> */ temp = temp2->super_class_
-              __ Ldr(temp, HeapOperand(temp2, super_offset));
-              // If heap poisoning is enabled, no need to unpoison
-              // `temp`, as we are comparing against null below.
-              __ Cbnz(temp, slow_path->GetEntryLabel());
-              __ Bind(&do_put);
-            } else {
-              __ B(ne, slow_path->GetEntryLabel());
-            }
-          }
-        } else {
-          // Non read barrier code.
-
-          Register temp2 = temps.AcquireSameSizeAs(array);
-          // /* HeapReference<Class> */ temp = array->klass_
-          __ Ldr(temp, HeapOperand(array, class_offset));
-          codegen_->MaybeRecordImplicitNullCheck(instruction);
+        if (instruction->StaticTypeOfArrayIsObjectArray()) {
+          vixl::aarch64::Label do_put;
+          __ B(eq, &do_put);
+          // If heap poisoning is enabled, the `temp` reference has
+          // not been unpoisoned yet; unpoison it now.
           GetAssembler()->MaybeUnpoisonHeapReference(temp);
 
-          // /* HeapReference<Class> */ temp = temp->component_type_
-          __ Ldr(temp, HeapOperand(temp, component_offset));
-          // /* HeapReference<Class> */ temp2 = value->klass_
-          __ Ldr(temp2, HeapOperand(Register(value), class_offset));
-          // If heap poisoning is enabled, no need to unpoison `temp`
-          // nor `temp2`, as we are comparing two poisoned references.
-          __ Cmp(temp, temp2);
-          temps.Release(temp2);
-
-          if (instruction->StaticTypeOfArrayIsObjectArray()) {
-            vixl::aarch64::Label do_put;
-            __ B(eq, &do_put);
-            // If heap poisoning is enabled, the `temp` reference has
-            // not been unpoisoned yet; unpoison it now.
-            GetAssembler()->MaybeUnpoisonHeapReference(temp);
-
-            // /* HeapReference<Class> */ temp = temp->super_class_
-            __ Ldr(temp, HeapOperand(temp, super_offset));
-            // If heap poisoning is enabled, no need to unpoison
-            // `temp`, as we are comparing against null below.
-            __ Cbnz(temp, slow_path->GetEntryLabel());
-            __ Bind(&do_put);
-          } else {
-            __ B(ne, slow_path->GetEntryLabel());
-          }
+          // /* HeapReference<Class> */ temp = temp->super_class_
+          __ Ldr(temp, HeapOperand(temp, super_offset));
+          // If heap poisoning is enabled, no need to unpoison
+          // `temp`, as we are comparing against null below.
+          __ Cbnz(temp, slow_path->GetEntryLabel());
+          __ Bind(&do_put);
+        } else {
+          __ B(ne, slow_path->GetEntryLabel());
         }
       }
 
@@ -4292,18 +4157,17 @@
 }
 
 void LocationsBuilderARM64::VisitLoadString(HLoadString* load) {
-  LocationSummary::CallKind call_kind = (load->NeedsEnvironment() || kEmitCompilerReadBarrier)
-      ? LocationSummary::kCallOnSlowPath
+  LocationSummary::CallKind call_kind = load->NeedsEnvironment()
+      ? LocationSummary::kCallOnMainOnly
       : LocationSummary::kNoCall;
   LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(load, call_kind);
-  if (kUseBakerReadBarrier && !load->NeedsEnvironment()) {
-    locations->SetCustomSlowPathCallerSaves(RegisterSet());  // No caller-save registers.
-  }
-
   if (load->GetLoadKind() == HLoadString::LoadKind::kDexCacheViaMethod) {
     locations->SetInAt(0, Location::RequiresRegister());
+    InvokeRuntimeCallingConvention calling_convention;
+    locations->SetOut(calling_convention.GetReturnLocation(load->GetType()));
+  } else {
+    locations->SetOut(Location::RequiresRegister());
   }
-  locations->SetOut(Location::RequiresRegister());
 }
 
 void InstructionCodeGeneratorARM64::VisitLoadString(HLoadString* load) {
@@ -4347,10 +4211,10 @@
   }
 
   // TODO: Re-add the compiler code to do string dex cache lookup again.
-  SlowPathCodeARM64* slow_path = new (GetGraph()->GetArena()) LoadStringSlowPathARM64(load);
-  codegen_->AddSlowPath(slow_path);
-  __ B(slow_path->GetEntryLabel());
-  __ Bind(slow_path->GetExitLabel());
+  InvokeRuntimeCallingConvention calling_convention;
+  __ Mov(calling_convention.GetRegisterAt(0).W(), load->GetStringIndex());
+  codegen_->InvokeRuntime(kQuickResolveString, load, load->GetDexPc());
+  CheckEntrypointTypes<kQuickResolveString, void*, uint32_t>();
 }
 
 void LocationsBuilderARM64::VisitLongConstant(HLongConstant* constant) {
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 92e9cd9..f07f8a0 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -2378,13 +2378,8 @@
 
     case Primitive::kPrimFloat:
     case Primitive::kPrimDouble:
-      // TODO: don't use branches.
-      GenerateFpCompareAndBranch(instruction->GetCondition(),
-                                 instruction->IsGtBias(),
-                                 type,
-                                 locations,
-                                 &true_label);
-      break;
+      GenerateFpCompare(instruction->GetCondition(), instruction->IsGtBias(), type, locations);
+      return;
   }
 
   // Convert the branches into the result.
@@ -3177,6 +3172,230 @@
   }
 }
 
+void InstructionCodeGeneratorMIPS::GenerateFpCompare(IfCondition cond,
+                                                     bool gt_bias,
+                                                     Primitive::Type type,
+                                                     LocationSummary* locations) {
+  Register dst = locations->Out().AsRegister<Register>();
+  FRegister lhs = locations->InAt(0).AsFpuRegister<FRegister>();
+  FRegister rhs = locations->InAt(1).AsFpuRegister<FRegister>();
+  bool isR6 = codegen_->GetInstructionSetFeatures().IsR6();
+  if (type == Primitive::kPrimFloat) {
+    if (isR6) {
+      switch (cond) {
+        case kCondEQ:
+          __ CmpEqS(FTMP, lhs, rhs);
+          __ Mfc1(dst, FTMP);
+          __ Andi(dst, dst, 1);
+          break;
+        case kCondNE:
+          __ CmpEqS(FTMP, lhs, rhs);
+          __ Mfc1(dst, FTMP);
+          __ Addiu(dst, dst, 1);
+          break;
+        case kCondLT:
+          if (gt_bias) {
+            __ CmpLtS(FTMP, lhs, rhs);
+          } else {
+            __ CmpUltS(FTMP, lhs, rhs);
+          }
+          __ Mfc1(dst, FTMP);
+          __ Andi(dst, dst, 1);
+          break;
+        case kCondLE:
+          if (gt_bias) {
+            __ CmpLeS(FTMP, lhs, rhs);
+          } else {
+            __ CmpUleS(FTMP, lhs, rhs);
+          }
+          __ Mfc1(dst, FTMP);
+          __ Andi(dst, dst, 1);
+          break;
+        case kCondGT:
+          if (gt_bias) {
+            __ CmpUltS(FTMP, rhs, lhs);
+          } else {
+            __ CmpLtS(FTMP, rhs, lhs);
+          }
+          __ Mfc1(dst, FTMP);
+          __ Andi(dst, dst, 1);
+          break;
+        case kCondGE:
+          if (gt_bias) {
+            __ CmpUleS(FTMP, rhs, lhs);
+          } else {
+            __ CmpLeS(FTMP, rhs, lhs);
+          }
+          __ Mfc1(dst, FTMP);
+          __ Andi(dst, dst, 1);
+          break;
+        default:
+          LOG(FATAL) << "Unexpected non-floating-point condition " << cond;
+          UNREACHABLE();
+      }
+    } else {
+      switch (cond) {
+        case kCondEQ:
+          __ CeqS(0, lhs, rhs);
+          __ LoadConst32(dst, 1);
+          __ Movf(dst, ZERO, 0);
+          break;
+        case kCondNE:
+          __ CeqS(0, lhs, rhs);
+          __ LoadConst32(dst, 1);
+          __ Movt(dst, ZERO, 0);
+          break;
+        case kCondLT:
+          if (gt_bias) {
+            __ ColtS(0, lhs, rhs);
+          } else {
+            __ CultS(0, lhs, rhs);
+          }
+          __ LoadConst32(dst, 1);
+          __ Movf(dst, ZERO, 0);
+          break;
+        case kCondLE:
+          if (gt_bias) {
+            __ ColeS(0, lhs, rhs);
+          } else {
+            __ CuleS(0, lhs, rhs);
+          }
+          __ LoadConst32(dst, 1);
+          __ Movf(dst, ZERO, 0);
+          break;
+        case kCondGT:
+          if (gt_bias) {
+            __ CultS(0, rhs, lhs);
+          } else {
+            __ ColtS(0, rhs, lhs);
+          }
+          __ LoadConst32(dst, 1);
+          __ Movf(dst, ZERO, 0);
+          break;
+        case kCondGE:
+          if (gt_bias) {
+            __ CuleS(0, rhs, lhs);
+          } else {
+            __ ColeS(0, rhs, lhs);
+          }
+          __ LoadConst32(dst, 1);
+          __ Movf(dst, ZERO, 0);
+          break;
+        default:
+          LOG(FATAL) << "Unexpected non-floating-point condition " << cond;
+          UNREACHABLE();
+      }
+    }
+  } else {
+    DCHECK_EQ(type, Primitive::kPrimDouble);
+    if (isR6) {
+      switch (cond) {
+        case kCondEQ:
+          __ CmpEqD(FTMP, lhs, rhs);
+          __ Mfc1(dst, FTMP);
+          __ Andi(dst, dst, 1);
+          break;
+        case kCondNE:
+          __ CmpEqD(FTMP, lhs, rhs);
+          __ Mfc1(dst, FTMP);
+          __ Addiu(dst, dst, 1);
+          break;
+        case kCondLT:
+          if (gt_bias) {
+            __ CmpLtD(FTMP, lhs, rhs);
+          } else {
+            __ CmpUltD(FTMP, lhs, rhs);
+          }
+          __ Mfc1(dst, FTMP);
+          __ Andi(dst, dst, 1);
+          break;
+        case kCondLE:
+          if (gt_bias) {
+            __ CmpLeD(FTMP, lhs, rhs);
+          } else {
+            __ CmpUleD(FTMP, lhs, rhs);
+          }
+          __ Mfc1(dst, FTMP);
+          __ Andi(dst, dst, 1);
+          break;
+        case kCondGT:
+          if (gt_bias) {
+            __ CmpUltD(FTMP, rhs, lhs);
+          } else {
+            __ CmpLtD(FTMP, rhs, lhs);
+          }
+          __ Mfc1(dst, FTMP);
+          __ Andi(dst, dst, 1);
+          break;
+        case kCondGE:
+          if (gt_bias) {
+            __ CmpUleD(FTMP, rhs, lhs);
+          } else {
+            __ CmpLeD(FTMP, rhs, lhs);
+          }
+          __ Mfc1(dst, FTMP);
+          __ Andi(dst, dst, 1);
+          break;
+        default:
+          LOG(FATAL) << "Unexpected non-floating-point condition " << cond;
+          UNREACHABLE();
+      }
+    } else {
+      switch (cond) {
+        case kCondEQ:
+          __ CeqD(0, lhs, rhs);
+          __ LoadConst32(dst, 1);
+          __ Movf(dst, ZERO, 0);
+          break;
+        case kCondNE:
+          __ CeqD(0, lhs, rhs);
+          __ LoadConst32(dst, 1);
+          __ Movt(dst, ZERO, 0);
+          break;
+        case kCondLT:
+          if (gt_bias) {
+            __ ColtD(0, lhs, rhs);
+          } else {
+            __ CultD(0, lhs, rhs);
+          }
+          __ LoadConst32(dst, 1);
+          __ Movf(dst, ZERO, 0);
+          break;
+        case kCondLE:
+          if (gt_bias) {
+            __ ColeD(0, lhs, rhs);
+          } else {
+            __ CuleD(0, lhs, rhs);
+          }
+          __ LoadConst32(dst, 1);
+          __ Movf(dst, ZERO, 0);
+          break;
+        case kCondGT:
+          if (gt_bias) {
+            __ CultD(0, rhs, lhs);
+          } else {
+            __ ColtD(0, rhs, lhs);
+          }
+          __ LoadConst32(dst, 1);
+          __ Movf(dst, ZERO, 0);
+          break;
+        case kCondGE:
+          if (gt_bias) {
+            __ CuleD(0, rhs, lhs);
+          } else {
+            __ ColeD(0, rhs, lhs);
+          }
+          __ LoadConst32(dst, 1);
+          __ Movf(dst, ZERO, 0);
+          break;
+        default:
+          LOG(FATAL) << "Unexpected non-floating-point condition " << cond;
+          UNREACHABLE();
+      }
+    }
+  }
+}
+
 void InstructionCodeGeneratorMIPS::GenerateFpCompareAndBranch(IfCondition cond,
                                                               bool gt_bias,
                                                               Primitive::Type type,
diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h
index 7ba6c0d..0039981 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -243,6 +243,10 @@
   void GenerateLongCompareAndBranch(IfCondition cond,
                                     LocationSummary* locations,
                                     MipsLabel* label);
+  void GenerateFpCompare(IfCondition cond,
+                         bool gt_bias,
+                         Primitive::Type type,
+                         LocationSummary* locations);
   void GenerateFpCompareAndBranch(IfCondition cond,
                                   bool gt_bias,
                                   Primitive::Type type,
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 4689ccb..b3b648f 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -5238,7 +5238,6 @@
   }
   if (needs_write_barrier) {
     // Temporary registers for the write barrier.
-    // These registers may be used for Baker read barriers too.
     locations->AddTemp(Location::RequiresRegister());  // Possibly used for ref. poisoning too.
     // Ensure the card is in a byte register.
     locations->AddTemp(Location::RegisterLocation(ECX));
@@ -5328,105 +5327,40 @@
           __ Bind(&not_null);
         }
 
-        if (kEmitCompilerReadBarrier) {
-          if (!kUseBakerReadBarrier) {
-            // When (non-Baker) read barriers are enabled, the type
-            // checking instrumentation requires two read barriers
-            // generated by CodeGeneratorX86::GenerateReadBarrierSlow:
-            //
-            //   __ movl(temp2, temp);
-            //   // /* HeapReference<Class> */ temp = temp->component_type_
-            //   __ movl(temp, Address(temp, component_offset));
-            //   codegen_->GenerateReadBarrierSlow(
-            //       instruction, temp_loc, temp_loc, temp2_loc, component_offset);
-            //
-            //   // /* HeapReference<Class> */ temp2 = register_value->klass_
-            //   __ movl(temp2, Address(register_value, class_offset));
-            //   codegen_->GenerateReadBarrierSlow(
-            //       instruction, temp2_loc, temp2_loc, value, class_offset, temp_loc);
-            //
-            //   __ cmpl(temp, temp2);
-            //
-            // However, the second read barrier may trash `temp`, as it
-            // is a temporary register, and as such would not be saved
-            // along with live registers before calling the runtime (nor
-            // restored afterwards).  So in this case, we bail out and
-            // delegate the work to the array set slow path.
-            //
-            // TODO: Extend the register allocator to support a new
-            // "(locally) live temp" location so as to avoid always
-            // going into the slow path when read barriers are enabled?
-            //
-            // There is no such problem with Baker read barriers (see below).
-            __ jmp(slow_path->GetEntryLabel());
-          } else {
-            Location temp2_loc = locations->GetTemp(1);
-            Register temp2 = temp2_loc.AsRegister<Register>();
-            // /* HeapReference<Class> */ temp = array->klass_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(
-                instruction, temp_loc, array, class_offset, /* needs_null_check */ true);
+        // Note that when Baker read barriers are enabled, the type
+        // checks are performed without read barriers.  This is fine,
+        // even in the case where a class object is in the from-space
+        // after the flip, as a comparison involving such a type would
+        // not produce a false positive; it may of course produce a
+        // false negative, in which case we would take the ArraySet
+        // slow path.
 
-            // /* HeapReference<Class> */ temp = temp->component_type_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(
-                instruction, temp_loc, temp, component_offset, /* needs_null_check */ false);
-            // Register `temp` is not trashed by the read barrier
-            // emitted by GenerateFieldLoadWithBakerReadBarrier below,
-            // as that method produces a call to a ReadBarrierMarkRegX
-            // entry point, which saves all potentially live registers,
-            // including temporaries such a `temp`.
-            // /* HeapReference<Class> */ temp2 = register_value->klass_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(
-                instruction, temp2_loc, register_value, class_offset, /* needs_null_check */ false);
-            // If heap poisoning is enabled, `temp` and `temp2` have
-            // been unpoisoned by the the previous calls to
-            // CodeGeneratorX86::GenerateFieldLoadWithBakerReadBarrier.
-            __ cmpl(temp, temp2);
+        // /* HeapReference<Class> */ temp = array->klass_
+        __ movl(temp, Address(array, class_offset));
+        codegen_->MaybeRecordImplicitNullCheck(instruction);
+        __ MaybeUnpoisonHeapReference(temp);
 
-            if (instruction->StaticTypeOfArrayIsObjectArray()) {
-              __ j(kEqual, &do_put);
-              // We do not need to emit a read barrier for the
-              // following heap reference load, as `temp` is only used
-              // in a comparison with null below, and this reference
-              // is not kept afterwards. Also, if heap poisoning is
-              // enabled, there is no need to unpoison that heap
-              // reference for the same reason (comparison with null).
-              __ cmpl(Address(temp, super_offset), Immediate(0));
-              __ j(kNotEqual, slow_path->GetEntryLabel());
-              __ Bind(&do_put);
-            } else {
-              __ j(kNotEqual, slow_path->GetEntryLabel());
-            }
-          }
-        } else {
-          // Non read barrier code.
+        // /* HeapReference<Class> */ temp = temp->component_type_
+        __ movl(temp, Address(temp, component_offset));
+        // If heap poisoning is enabled, no need to unpoison `temp`
+        // nor the object reference in `register_value->klass`, as
+        // we are comparing two poisoned references.
+        __ cmpl(temp, Address(register_value, class_offset));
 
-          // /* HeapReference<Class> */ temp = array->klass_
-          __ movl(temp, Address(array, class_offset));
-          codegen_->MaybeRecordImplicitNullCheck(instruction);
+        if (instruction->StaticTypeOfArrayIsObjectArray()) {
+          __ j(kEqual, &do_put);
+          // If heap poisoning is enabled, the `temp` reference has
+          // not been unpoisoned yet; unpoison it now.
           __ MaybeUnpoisonHeapReference(temp);
 
-          // /* HeapReference<Class> */ temp = temp->component_type_
-          __ movl(temp, Address(temp, component_offset));
-          // If heap poisoning is enabled, no need to unpoison `temp`
-          // nor the object reference in `register_value->klass`, as
-          // we are comparing two poisoned references.
-          __ cmpl(temp, Address(register_value, class_offset));
-
-          if (instruction->StaticTypeOfArrayIsObjectArray()) {
-            __ j(kEqual, &do_put);
-            // If heap poisoning is enabled, the `temp` reference has
-            // not been unpoisoned yet; unpoison it now.
-            __ MaybeUnpoisonHeapReference(temp);
-
-            // If heap poisoning is enabled, no need to unpoison the
-            // heap reference loaded below, as it is only used for a
-            // comparison with null.
-            __ cmpl(Address(temp, super_offset), Immediate(0));
-            __ j(kNotEqual, slow_path->GetEntryLabel());
-            __ Bind(&do_put);
-          } else {
-            __ j(kNotEqual, slow_path->GetEntryLabel());
-          }
+          // If heap poisoning is enabled, no need to unpoison the
+          // heap reference loaded below, as it is only used for a
+          // comparison with null.
+          __ cmpl(Address(temp, super_offset), Immediate(0));
+          __ j(kNotEqual, slow_path->GetEntryLabel());
+          __ Bind(&do_put);
+        } else {
+          __ j(kNotEqual, slow_path->GetEntryLabel());
         }
       }
 
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index a21a09e..b3228f8 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -4732,7 +4732,6 @@
 
   if (needs_write_barrier) {
     // Temporary registers for the write barrier.
-    // These registers may be used for Baker read barriers too.
     locations->AddTemp(Location::RequiresRegister());  // Possibly used for ref. poisoning too.
     locations->AddTemp(Location::RequiresRegister());
   }
@@ -4822,105 +4821,40 @@
           __ Bind(&not_null);
         }
 
-        if (kEmitCompilerReadBarrier) {
-          if (!kUseBakerReadBarrier) {
-            // When (non-Baker) read barriers are enabled, the type
-            // checking instrumentation requires two read barriers
-            // generated by CodeGeneratorX86_64::GenerateReadBarrierSlow:
-            //
-            //   __ movl(temp2, temp);
-            //   // /* HeapReference<Class> */ temp = temp->component_type_
-            //   __ movl(temp, Address(temp, component_offset));
-            //   codegen_->GenerateReadBarrierSlow(
-            //       instruction, temp_loc, temp_loc, temp2_loc, component_offset);
-            //
-            //   // /* HeapReference<Class> */ temp2 = register_value->klass_
-            //   __ movl(temp2, Address(register_value, class_offset));
-            //   codegen_->GenerateReadBarrierSlow(
-            //       instruction, temp2_loc, temp2_loc, value, class_offset, temp_loc);
-            //
-            //   __ cmpl(temp, temp2);
-            //
-            // However, the second read barrier may trash `temp`, as it
-            // is a temporary register, and as such would not be saved
-            // along with live registers before calling the runtime (nor
-            // restored afterwards).  So in this case, we bail out and
-            // delegate the work to the array set slow path.
-            //
-            // TODO: Extend the register allocator to support a new
-            // "(locally) live temp" location so as to avoid always
-            // going into the slow path when read barriers are enabled?
-            //
-            // There is no such problem with Baker read barriers (see below).
-            __ jmp(slow_path->GetEntryLabel());
-          } else {
-            Location temp2_loc = locations->GetTemp(1);
-            CpuRegister temp2 = temp2_loc.AsRegister<CpuRegister>();
-            // /* HeapReference<Class> */ temp = array->klass_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(
-                instruction, temp_loc, array, class_offset, /* needs_null_check */ true);
+        // Note that when Baker read barriers are enabled, the type
+        // checks are performed without read barriers.  This is fine,
+        // even in the case where a class object is in the from-space
+        // after the flip, as a comparison involving such a type would
+        // not produce a false positive; it may of course produce a
+        // false negative, in which case we would take the ArraySet
+        // slow path.
 
-            // /* HeapReference<Class> */ temp = temp->component_type_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(
-                instruction, temp_loc, temp, component_offset, /* needs_null_check */ false);
-            // Register `temp` is not trashed by the read barrier
-            // emitted by GenerateFieldLoadWithBakerReadBarrier below,
-            // as that method produces a call to a ReadBarrierMarkRegX
-            // entry point, which saves all potentially live registers,
-            // including temporaries such a `temp`.
-            // /* HeapReference<Class> */ temp2 = register_value->klass_
-            codegen_->GenerateFieldLoadWithBakerReadBarrier(
-                instruction, temp2_loc, register_value, class_offset, /* needs_null_check */ false);
-            // If heap poisoning is enabled, `temp` and `temp2` have
-            // been unpoisoned by the the previous calls to
-            // CodeGeneratorX86_64::GenerateFieldLoadWithBakerReadBarrier.
-            __ cmpl(temp, temp2);
+        // /* HeapReference<Class> */ temp = array->klass_
+        __ movl(temp, Address(array, class_offset));
+        codegen_->MaybeRecordImplicitNullCheck(instruction);
+        __ MaybeUnpoisonHeapReference(temp);
 
-            if (instruction->StaticTypeOfArrayIsObjectArray()) {
-              __ j(kEqual, &do_put);
-              // We do not need to emit a read barrier for the
-              // following heap reference load, as `temp` is only used
-              // in a comparison with null below, and this reference
-              // is not kept afterwards. Also, if heap poisoning is
-              // enabled, there is no need to unpoison that heap
-              // reference for the same reason (comparison with null).
-              __ cmpl(Address(temp, super_offset), Immediate(0));
-              __ j(kNotEqual, slow_path->GetEntryLabel());
-              __ Bind(&do_put);
-            } else {
-              __ j(kNotEqual, slow_path->GetEntryLabel());
-            }
-          }
-        } else {
-          // Non read barrier code.
+        // /* HeapReference<Class> */ temp = temp->component_type_
+        __ movl(temp, Address(temp, component_offset));
+        // If heap poisoning is enabled, no need to unpoison `temp`
+        // nor the object reference in `register_value->klass`, as
+        // we are comparing two poisoned references.
+        __ cmpl(temp, Address(register_value, class_offset));
 
-          // /* HeapReference<Class> */ temp = array->klass_
-          __ movl(temp, Address(array, class_offset));
-          codegen_->MaybeRecordImplicitNullCheck(instruction);
+        if (instruction->StaticTypeOfArrayIsObjectArray()) {
+          __ j(kEqual, &do_put);
+          // If heap poisoning is enabled, the `temp` reference has
+          // not been unpoisoned yet; unpoison it now.
           __ MaybeUnpoisonHeapReference(temp);
 
-          // /* HeapReference<Class> */ temp = temp->component_type_
-          __ movl(temp, Address(temp, component_offset));
-          // If heap poisoning is enabled, no need to unpoison `temp`
-          // nor the object reference in `register_value->klass`, as
-          // we are comparing two poisoned references.
-          __ cmpl(temp, Address(register_value, class_offset));
-
-          if (instruction->StaticTypeOfArrayIsObjectArray()) {
-            __ j(kEqual, &do_put);
-            // If heap poisoning is enabled, the `temp` reference has
-            // not been unpoisoned yet; unpoison it now.
-            __ MaybeUnpoisonHeapReference(temp);
-
-            // If heap poisoning is enabled, no need to unpoison the
-            // heap reference loaded below, as it is only used for a
-            // comparison with null.
-            __ cmpl(Address(temp, super_offset), Immediate(0));
-            __ j(kNotEqual, slow_path->GetEntryLabel());
-            __ Bind(&do_put);
-          } else {
-            __ j(kNotEqual, slow_path->GetEntryLabel());
-          }
+          // If heap poisoning is enabled, no need to unpoison the
+          // heap reference loaded below, as it is only used for a
+          // comparison with null.
+          __ cmpl(Address(temp, super_offset), Immediate(0));
+          __ j(kNotEqual, slow_path->GetEntryLabel());
+          __ Bind(&do_put);
+        } else {
+          __ j(kNotEqual, slow_path->GetEntryLabel());
         }
       }
 
diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h
index cea4a7e..eda0971 100644
--- a/compiler/optimizing/common_arm64.h
+++ b/compiler/optimizing/common_arm64.h
@@ -38,7 +38,7 @@
 static_assert((SP == 31) && (WSP == 31) && (XZR == 32) && (WZR == 32),
               "Unexpected values for register codes.");
 
-static inline int VIXLRegCodeFromART(int code) {
+inline int VIXLRegCodeFromART(int code) {
   if (code == SP) {
     return vixl::aarch64::kSPRegInternalCode;
   }
@@ -48,7 +48,7 @@
   return code;
 }
 
-static inline int ARTRegCodeFromVIXL(int code) {
+inline int ARTRegCodeFromVIXL(int code) {
   if (code == vixl::aarch64::kSPRegInternalCode) {
     return SP;
   }
@@ -58,85 +58,85 @@
   return code;
 }
 
-static inline vixl::aarch64::Register XRegisterFrom(Location location) {
+inline vixl::aarch64::Register XRegisterFrom(Location location) {
   DCHECK(location.IsRegister()) << location;
   return vixl::aarch64::Register::GetXRegFromCode(VIXLRegCodeFromART(location.reg()));
 }
 
-static inline vixl::aarch64::Register WRegisterFrom(Location location) {
+inline vixl::aarch64::Register WRegisterFrom(Location location) {
   DCHECK(location.IsRegister()) << location;
   return vixl::aarch64::Register::GetWRegFromCode(VIXLRegCodeFromART(location.reg()));
 }
 
-static inline vixl::aarch64::Register RegisterFrom(Location location, Primitive::Type type) {
+inline vixl::aarch64::Register RegisterFrom(Location location, Primitive::Type type) {
   DCHECK(type != Primitive::kPrimVoid && !Primitive::IsFloatingPointType(type)) << type;
   return type == Primitive::kPrimLong ? XRegisterFrom(location) : WRegisterFrom(location);
 }
 
-static inline vixl::aarch64::Register OutputRegister(HInstruction* instr) {
+inline vixl::aarch64::Register OutputRegister(HInstruction* instr) {
   return RegisterFrom(instr->GetLocations()->Out(), instr->GetType());
 }
 
-static inline vixl::aarch64::Register InputRegisterAt(HInstruction* instr, int input_index) {
+inline vixl::aarch64::Register InputRegisterAt(HInstruction* instr, int input_index) {
   return RegisterFrom(instr->GetLocations()->InAt(input_index),
                       instr->InputAt(input_index)->GetType());
 }
 
-static inline vixl::aarch64::FPRegister DRegisterFrom(Location location) {
+inline vixl::aarch64::FPRegister DRegisterFrom(Location location) {
   DCHECK(location.IsFpuRegister()) << location;
   return vixl::aarch64::FPRegister::GetDRegFromCode(location.reg());
 }
 
-static inline vixl::aarch64::FPRegister SRegisterFrom(Location location) {
+inline vixl::aarch64::FPRegister SRegisterFrom(Location location) {
   DCHECK(location.IsFpuRegister()) << location;
   return vixl::aarch64::FPRegister::GetSRegFromCode(location.reg());
 }
 
-static inline vixl::aarch64::FPRegister FPRegisterFrom(Location location, Primitive::Type type) {
+inline vixl::aarch64::FPRegister FPRegisterFrom(Location location, Primitive::Type type) {
   DCHECK(Primitive::IsFloatingPointType(type)) << type;
   return type == Primitive::kPrimDouble ? DRegisterFrom(location) : SRegisterFrom(location);
 }
 
-static inline vixl::aarch64::FPRegister OutputFPRegister(HInstruction* instr) {
+inline vixl::aarch64::FPRegister OutputFPRegister(HInstruction* instr) {
   return FPRegisterFrom(instr->GetLocations()->Out(), instr->GetType());
 }
 
-static inline vixl::aarch64::FPRegister InputFPRegisterAt(HInstruction* instr, int input_index) {
+inline vixl::aarch64::FPRegister InputFPRegisterAt(HInstruction* instr, int input_index) {
   return FPRegisterFrom(instr->GetLocations()->InAt(input_index),
                         instr->InputAt(input_index)->GetType());
 }
 
-static inline vixl::aarch64::CPURegister CPURegisterFrom(Location location, Primitive::Type type) {
+inline vixl::aarch64::CPURegister CPURegisterFrom(Location location, Primitive::Type type) {
   return Primitive::IsFloatingPointType(type)
       ? vixl::aarch64::CPURegister(FPRegisterFrom(location, type))
       : vixl::aarch64::CPURegister(RegisterFrom(location, type));
 }
 
-static inline vixl::aarch64::CPURegister OutputCPURegister(HInstruction* instr) {
+inline vixl::aarch64::CPURegister OutputCPURegister(HInstruction* instr) {
   return Primitive::IsFloatingPointType(instr->GetType())
       ? static_cast<vixl::aarch64::CPURegister>(OutputFPRegister(instr))
       : static_cast<vixl::aarch64::CPURegister>(OutputRegister(instr));
 }
 
-static inline vixl::aarch64::CPURegister InputCPURegisterAt(HInstruction* instr, int index) {
+inline vixl::aarch64::CPURegister InputCPURegisterAt(HInstruction* instr, int index) {
   return Primitive::IsFloatingPointType(instr->InputAt(index)->GetType())
       ? static_cast<vixl::aarch64::CPURegister>(InputFPRegisterAt(instr, index))
       : static_cast<vixl::aarch64::CPURegister>(InputRegisterAt(instr, index));
 }
 
-static inline vixl::aarch64::CPURegister InputCPURegisterOrZeroRegAt(HInstruction* instr,
+inline vixl::aarch64::CPURegister InputCPURegisterOrZeroRegAt(HInstruction* instr,
                                                                      int index) {
   HInstruction* input = instr->InputAt(index);
   Primitive::Type input_type = input->GetType();
   if (input->IsConstant() && input->AsConstant()->IsZeroBitPattern()) {
     return (Primitive::ComponentSize(input_type) >= vixl::aarch64::kXRegSizeInBytes)
-        ?  vixl::aarch64::xzr
+        ? vixl::aarch64::xzr
         : vixl::aarch64::wzr;
   }
   return InputCPURegisterAt(instr, index);
 }
 
-static inline int64_t Int64ConstantFrom(Location location) {
+inline int64_t Int64ConstantFrom(Location location) {
   HConstant* instr = location.GetConstant();
   if (instr->IsIntConstant()) {
     return instr->AsIntConstant()->GetValue();
@@ -148,7 +148,7 @@
   }
 }
 
-static inline vixl::aarch64::Operand OperandFrom(Location location, Primitive::Type type) {
+inline vixl::aarch64::Operand OperandFrom(Location location, Primitive::Type type) {
   if (location.IsRegister()) {
     return vixl::aarch64::Operand(RegisterFrom(location, type));
   } else {
@@ -156,23 +156,23 @@
   }
 }
 
-static inline vixl::aarch64::Operand InputOperandAt(HInstruction* instr, int input_index) {
+inline vixl::aarch64::Operand InputOperandAt(HInstruction* instr, int input_index) {
   return OperandFrom(instr->GetLocations()->InAt(input_index),
                      instr->InputAt(input_index)->GetType());
 }
 
-static inline vixl::aarch64::MemOperand StackOperandFrom(Location location) {
+inline vixl::aarch64::MemOperand StackOperandFrom(Location location) {
   return vixl::aarch64::MemOperand(vixl::aarch64::sp, location.GetStackIndex());
 }
 
-static inline vixl::aarch64::MemOperand HeapOperand(const vixl::aarch64::Register& base,
+inline vixl::aarch64::MemOperand HeapOperand(const vixl::aarch64::Register& base,
                                                     size_t offset = 0) {
   // A heap reference must be 32bit, so fit in a W register.
   DCHECK(base.IsW());
   return vixl::aarch64::MemOperand(base.X(), offset);
 }
 
-static inline vixl::aarch64::MemOperand HeapOperand(const vixl::aarch64::Register& base,
+inline vixl::aarch64::MemOperand HeapOperand(const vixl::aarch64::Register& base,
                                                     const vixl::aarch64::Register& regoffset,
                                                     vixl::aarch64::Shift shift = vixl::aarch64::LSL,
                                                     unsigned shift_amount = 0) {
@@ -181,24 +181,24 @@
   return vixl::aarch64::MemOperand(base.X(), regoffset, shift, shift_amount);
 }
 
-static inline vixl::aarch64::MemOperand HeapOperand(const vixl::aarch64::Register& base,
+inline vixl::aarch64::MemOperand HeapOperand(const vixl::aarch64::Register& base,
                                                     Offset offset) {
   return HeapOperand(base, offset.SizeValue());
 }
 
-static inline vixl::aarch64::MemOperand HeapOperandFrom(Location location, Offset offset) {
+inline vixl::aarch64::MemOperand HeapOperandFrom(Location location, Offset offset) {
   return HeapOperand(RegisterFrom(location, Primitive::kPrimNot), offset);
 }
 
-static inline Location LocationFrom(const vixl::aarch64::Register& reg) {
+inline Location LocationFrom(const vixl::aarch64::Register& reg) {
   return Location::RegisterLocation(ARTRegCodeFromVIXL(reg.GetCode()));
 }
 
-static inline Location LocationFrom(const vixl::aarch64::FPRegister& fpreg) {
+inline Location LocationFrom(const vixl::aarch64::FPRegister& fpreg) {
   return Location::FpuRegisterLocation(fpreg.GetCode());
 }
 
-static inline vixl::aarch64::Operand OperandFromMemOperand(
+inline vixl::aarch64::Operand OperandFromMemOperand(
     const vixl::aarch64::MemOperand& mem_op) {
   if (mem_op.IsImmediateOffset()) {
     return vixl::aarch64::Operand(mem_op.GetOffset());
@@ -219,7 +219,7 @@
   }
 }
 
-static bool CanEncodeConstantAsImmediate(HConstant* constant, HInstruction* instr) {
+inline bool CanEncodeConstantAsImmediate(HConstant* constant, HInstruction* instr) {
   DCHECK(constant->IsIntConstant() || constant->IsLongConstant() || constant->IsNullConstant())
       << constant->DebugName();
 
@@ -258,7 +258,7 @@
   }
 }
 
-static inline Location ARM64EncodableConstantOrRegister(HInstruction* constant,
+inline Location ARM64EncodableConstantOrRegister(HInstruction* constant,
                                                         HInstruction* instr) {
   if (constant->IsConstant()
       && CanEncodeConstantAsImmediate(constant->AsConstant(), instr)) {
@@ -272,7 +272,7 @@
 // codes are same, we can initialize vixl register list simply by the register masks. Currently,
 // only SP/WSP and ZXR/WZR codes are different between art and vixl.
 // Note: This function is only used for debug checks.
-static inline bool ArtVixlRegCodeCoherentForRegSet(uint32_t art_core_registers,
+inline bool ArtVixlRegCodeCoherentForRegSet(uint32_t art_core_registers,
                                                    size_t num_core,
                                                    uint32_t art_fpu_registers,
                                                    size_t num_fpu) {
@@ -290,7 +290,7 @@
   return true;
 }
 
-static inline vixl::aarch64::Shift ShiftFromOpKind(HArm64DataProcWithShifterOp::OpKind op_kind) {
+inline vixl::aarch64::Shift ShiftFromOpKind(HArm64DataProcWithShifterOp::OpKind op_kind) {
   switch (op_kind) {
     case HArm64DataProcWithShifterOp::kASR: return vixl::aarch64::ASR;
     case HArm64DataProcWithShifterOp::kLSL: return vixl::aarch64::LSL;
@@ -302,7 +302,7 @@
   }
 }
 
-static inline vixl::aarch64::Extend ExtendFromOpKind(HArm64DataProcWithShifterOp::OpKind op_kind) {
+inline vixl::aarch64::Extend ExtendFromOpKind(HArm64DataProcWithShifterOp::OpKind op_kind) {
   switch (op_kind) {
     case HArm64DataProcWithShifterOp::kUXTB: return vixl::aarch64::UXTB;
     case HArm64DataProcWithShifterOp::kUXTH: return vixl::aarch64::UXTH;
@@ -317,7 +317,7 @@
   }
 }
 
-static inline bool CanFitInShifterOperand(HInstruction* instruction) {
+inline bool CanFitInShifterOperand(HInstruction* instruction) {
   if (instruction->IsTypeConversion()) {
     HTypeConversion* conversion = instruction->AsTypeConversion();
     Primitive::Type result_type = conversion->GetResultType();
@@ -332,7 +332,7 @@
   }
 }
 
-static inline bool HasShifterOperand(HInstruction* instr) {
+inline bool HasShifterOperand(HInstruction* instr) {
   // `neg` instructions are an alias of `sub` using the zero register as the
   // first register input.
   bool res = instr->IsAdd() || instr->IsAnd() || instr->IsNeg() ||
@@ -340,7 +340,7 @@
   return res;
 }
 
-static inline bool ShifterOperandSupportsExtension(HInstruction* instruction) {
+inline bool ShifterOperandSupportsExtension(HInstruction* instruction) {
   DCHECK(HasShifterOperand(instruction));
   // Although the `neg` instruction is an alias of the `sub` instruction, `HNeg`
   // does *not* support extension. This is because the `extended register` form
@@ -351,7 +351,7 @@
   return instruction->IsAdd() || instruction->IsSub();
 }
 
-static inline bool IsConstantZeroBitPattern(const HInstruction* instruction) {
+inline bool IsConstantZeroBitPattern(const HInstruction* instruction) {
   return instruction->IsConstant() && instruction->AsConstant()->IsZeroBitPattern();
 }
 
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 8d4d143..b8e1379 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -297,7 +297,15 @@
       DCHECK(!runtime->UseJitCompilation());
       mirror::String* string = class_linker->ResolveString(dex_file, string_index, dex_cache);
       CHECK(string != nullptr);
-      // TODO: In follow up CL, add PcRelative and Address back in.
+      if (compiler_driver_->GetSupportBootImageFixup()) {
+        DCHECK(ContainsElement(compiler_driver_->GetDexFilesForOatFile(), &dex_file));
+        desired_load_kind = codegen_->GetCompilerOptions().GetCompilePic()
+            ? HLoadString::LoadKind::kBootImageLinkTimePcRelative
+            : HLoadString::LoadKind::kBootImageLinkTimeAddress;
+      } else {
+        // MIPS64 or compiler_driver_test. Do not sharpen.
+        DCHECK_EQ(desired_load_kind, HLoadString::LoadKind::kDexCacheViaMethod);
+      }
     } else if (runtime->UseJitCompilation()) {
       // TODO: Make sure we don't set the "compile PIC" flag for JIT as that's bogus.
       // DCHECK(!codegen_->GetCompilerOptions().GetCompilePic());
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index f2ef41f..cd30872 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -1708,6 +1708,13 @@
 }
 
 
+void X86Assembler::repne_scasb() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0xAE);
+}
+
+
 void X86Assembler::repne_scasw() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
@@ -1716,6 +1723,13 @@
 }
 
 
+void X86Assembler::repe_cmpsb() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0xA6);
+}
+
+
 void X86Assembler::repe_cmpsw() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
@@ -1731,6 +1745,13 @@
 }
 
 
+void X86Assembler::rep_movsb() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF3);
+  EmitUint8(0xA4);
+}
+
+
 void X86Assembler::rep_movsw() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 2ddcd76..9738784 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -592,9 +592,12 @@
   void jmp(Label* label);
   void jmp(NearLabel* label);
 
+  void repne_scasb();
   void repne_scasw();
+  void repe_cmpsb();
   void repe_cmpsw();
   void repe_cmpsl();
+  void rep_movsb();
   void rep_movsw();
 
   X86Assembler* lock();
diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc
index 61d70d7..9bae6c2 100644
--- a/compiler/utils/x86/assembler_x86_test.cc
+++ b/compiler/utils/x86/assembler_x86_test.cc
@@ -207,12 +207,24 @@
   DriverStr(expected, "FPUIntegerStore");
 }
 
+TEST_F(AssemblerX86Test, Repnescasb) {
+  GetAssembler()->repne_scasb();
+  const char* expected = "repne scasb\n";
+  DriverStr(expected, "Repnescasb");
+}
+
 TEST_F(AssemblerX86Test, Repnescasw) {
   GetAssembler()->repne_scasw();
   const char* expected = "repne scasw\n";
   DriverStr(expected, "Repnescasw");
 }
 
+TEST_F(AssemblerX86Test, Repecmpsb) {
+  GetAssembler()->repe_cmpsb();
+  const char* expected = "repe cmpsb\n";
+  DriverStr(expected, "Repecmpsb");
+}
+
 TEST_F(AssemblerX86Test, Repecmpsw) {
   GetAssembler()->repe_cmpsw();
   const char* expected = "repe cmpsw\n";
@@ -225,10 +237,10 @@
   DriverStr(expected, "Repecmpsl");
 }
 
-TEST_F(AssemblerX86Test, RepneScasw) {
-  GetAssembler()->repne_scasw();
-  const char* expected = "repne scasw\n";
-  DriverStr(expected, "repne_scasw");
+TEST_F(AssemblerX86Test, RepMovsb) {
+  GetAssembler()->rep_movsb();
+  const char* expected = "rep movsb\n";
+  DriverStr(expected, "rep_movsb");
 }
 
 TEST_F(AssemblerX86Test, RepMovsw) {
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 1f73aa7..e9a0607 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -2325,6 +2325,12 @@
   EmitOperand(dst.LowBits(), src);
 }
 
+void X86_64Assembler::repne_scasb() {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xF2);
+  EmitUint8(0xAE);
+}
+
 void X86_64Assembler::repne_scasw() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
@@ -2332,7 +2338,6 @@
   EmitUint8(0xAF);
 }
 
-
 void X86_64Assembler::repe_cmpsw() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0x66);
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 3a4bfca..fdd3aa9 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -670,6 +670,7 @@
   void rolq(CpuRegister reg, const Immediate& imm);
   void rolq(CpuRegister operand, CpuRegister shifter);
 
+  void repne_scasb();
   void repne_scasw();
   void repe_cmpsw();
   void repe_cmpsl();
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 48a1876..ff01429 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -956,6 +956,12 @@
   DriverStr(expected, "xorq");
 }
 
+TEST_F(AssemblerX86_64Test, RepneScasb) {
+  GetAssembler()->repne_scasb();
+  const char* expected = "repne scasb\n";
+  DriverStr(expected, "repne_scasb");
+}
+
 TEST_F(AssemblerX86_64Test, RepneScasw) {
   GetAssembler()->repne_scasw();
   const char* expected = "repne scasw\n";
diff --git a/dalvikvm/Android.bp b/dalvikvm/Android.bp
new file mode 100644
index 0000000..ab645bb
--- /dev/null
+++ b/dalvikvm/Android.bp
@@ -0,0 +1,63 @@
+//
+// Copyright (C) 2013 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.
+//
+
+art_cc_binary {
+    name: "dalvikvm",
+    host_supported: true,
+    compile_multilib: "both",
+
+    srcs: ["dalvikvm.cc"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    include_dirs: ["art/runtime"],
+    shared_libs: [
+        "libnativehelper",
+    ],
+    whole_static_libs: ["libsigchain"],
+    target: {
+        host: {
+            host_ldlibs: [
+                "-ldl",
+                "-lpthread",
+            ],
+        },
+        android: {
+            shared_libs: [
+                "libdl",
+                "liblog",
+            ],
+            ldflags: ["-Wl,--export-dynamic"],
+        },
+        linux: {
+            ldflags: ["-Wl,--export-dynamic"],
+        },
+    },
+
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+
+    // Create symlink for the primary version target.
+    symlink_preferred_arch: true,
+}
diff --git a/dalvikvm/Android.mk b/dalvikvm/Android.mk
deleted file mode 100644
index 6c0bcb1..0000000
--- a/dalvikvm/Android.mk
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# Copyright (C) 2013 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include art/build/Android.common.mk
-
-dalvikvm_cflags := -Wall -Werror -Wextra
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := dalvikvm
-LOCAL_MODULE_TAGS := optional
-LOCAL_CPP_EXTENSION := cc
-LOCAL_SRC_FILES := dalvikvm.cc
-LOCAL_CFLAGS := $(dalvikvm_cflags)
-LOCAL_C_INCLUDES := art/runtime
-LOCAL_SHARED_LIBRARIES := libdl liblog libnativehelper
-LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
-LOCAL_LDFLAGS := -Wl,--export-dynamic
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.common.mk
-LOCAL_MULTILIB := both
-LOCAL_MODULE_STEM_32 := dalvikvm32
-LOCAL_MODULE_STEM_64 := dalvikvm64
-LOCAL_NATIVE_COVERAGE := $(ART_COVERAGE)
-include $(BUILD_EXECUTABLE)
-
-# Create symlink for the primary version target.
-include  $(BUILD_SYSTEM)/executable_prefer_symlink.mk
-
-ART_TARGET_EXECUTABLES += $(TARGET_OUT_EXECUTABLES)/$(LOCAL_MODULE)
-ART_TARGET_EXECUTABLES += $(TARGET_OUT_EXECUTABLES)/$(LOCAL_MODULE)$(ART_PHONY_TEST_TARGET_SUFFIX)
-ifdef 2ND_ART_PHONY_TEST_TARGET_SUFFIX
-  ART_TARGET_EXECUTABLES += $(TARGET_OUT_EXECUTABLES)/$(LOCAL_MODULE)$(2ND_ART_PHONY_TEST_TARGET_SUFFIX)
-endif
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := dalvikvm
-LOCAL_MODULE_TAGS := optional
-LOCAL_CLANG := true
-LOCAL_CPP_EXTENSION := cc
-LOCAL_SRC_FILES := dalvikvm.cc
-LOCAL_CFLAGS := $(dalvikvm_cflags)
-LOCAL_C_INCLUDES := art/runtime
-LOCAL_SHARED_LIBRARIES := libnativehelper
-LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
-LOCAL_LDFLAGS := -ldl -lpthread
-# Mac OS linker doesn't understand --export-dynamic.
-ifneq ($(HOST_OS),darwin)
-  LOCAL_LDFLAGS += -Wl,--export-dynamic
-endif
-LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
-LOCAL_ADDITIONAL_DEPENDENCIES += art/build/Android.common.mk
-LOCAL_IS_HOST_MODULE := true
-LOCAL_MULTILIB := both
-ifdef ART_MULTILIB_OVERRIDE_host
-  LOCAL_MULTILIB := $(ART_MULTILIB_OVERRIDE_host)
-endif
-ifeq ($(LOCAL_MULTILIB),both)
-LOCAL_MODULE_STEM_32 := dalvikvm32
-LOCAL_MODULE_STEM_64 := dalvikvm64
-endif
-LOCAL_NATIVE_COVERAGE := $(ART_COVERAGE)
-include $(BUILD_HOST_EXECUTABLE)
-# Create symlink for the primary version target.
-ifeq ($(LOCAL_MULTILIB),both)
-include  $(BUILD_SYSTEM)/executable_prefer_symlink.mk
-
-ART_HOST_EXECUTABLES += $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)$(ART_PHONY_TEST_HOST_SUFFIX)
-ifdef 2ND_ART_PHONY_TEST_HOST_SUFFIX
-  ART_HOST_EXECUTABLES += $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)$(2ND_ART_PHONY_TEST_HOST_SUFFIX)
-endif
-endif
-ART_HOST_EXECUTABLES += $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)
diff --git a/dexdump/Android.bp b/dexdump/Android.bp
new file mode 100644
index 0000000..e77f809
--- /dev/null
+++ b/dexdump/Android.bp
@@ -0,0 +1,26 @@
+// 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.
+
+// TODO(ajcbik): rename dexdump2 into dexdump when Dalvik version is removed
+
+art_cc_binary {
+    name: "dexdump2",
+    host_supported: true,
+    srcs: [
+        "dexdump_main.cc",
+        "dexdump.cc",
+    ],
+    cflags: ["-Wall"],
+    shared_libs: ["libart"],
+}
diff --git a/dexdump/Android.mk b/dexdump/Android.mk
deleted file mode 100755
index ec2529e..0000000
--- a/dexdump/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# 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.
-
-# TODO(ajcbik): Art-i-fy this makefile
-
-# TODO(ajcbik): rename dexdump2 into dexdump when Dalvik version is removed
-
-LOCAL_PATH:= $(call my-dir)
-
-dexdump_src_files := dexdump_main.cc dexdump.cc
-dexdump_c_includes := art/runtime
-dexdump_libraries := libart
-
-##
-## Build the device command line tool dexdump.
-##
-
-ifneq ($(SDK_ONLY),true)  # SDK_only doesn't need device version
-include $(CLEAR_VARS)
-LOCAL_CPP_EXTENSION := cc
-LOCAL_SRC_FILES := $(dexdump_src_files)
-LOCAL_C_INCLUDES := $(dexdump_c_includes)
-LOCAL_CFLAGS += -Wall
-LOCAL_SHARED_LIBRARIES += $(dexdump_libraries)
-LOCAL_MODULE := dexdump2
-include $(BUILD_EXECUTABLE)
-endif # !SDK_ONLY
-
-##
-## Build the host command line tool dexdump.
-##
-
-include $(CLEAR_VARS)
-LOCAL_CPP_EXTENSION := cc
-LOCAL_SRC_FILES := $(dexdump_src_files)
-LOCAL_C_INCLUDES := $(dexdump_c_includes)
-LOCAL_CFLAGS += -Wall
-LOCAL_SHARED_LIBRARIES += $(dexdump_libraries)
-LOCAL_MODULE := dexdump2
-LOCAL_MULTILIB := $(ART_MULTILIB_OVERRIDE_host)
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
new file mode 100644
index 0000000..852f6c2
--- /dev/null
+++ b/dexlayout/Android.bp
@@ -0,0 +1,25 @@
+// Copyright (C) 2016 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.
+
+art_cc_binary {
+    name: "dexlayout",
+    host_supported: true,
+    srcs: [
+        "dexlayout_main.cc",
+        "dexlayout.cc",
+        "dex_ir_builder.cc",
+    ],
+    cflags: ["-Wall"],
+    shared_libs: ["libart"],
+}
diff --git a/dexlayout/Android.mk b/dexlayout/Android.mk
deleted file mode 100755
index de02580..0000000
--- a/dexlayout/Android.mk
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (C) 2016 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.
-
-# TODO(sehr): Art-i-fy this makefile
-
-LOCAL_PATH:= $(call my-dir)
-
-dexlayout_src_files := dexlayout_main.cc dexlayout.cc dex_ir_builder.cc
-dexlayout_c_includes := art/runtime
-dexlayout_libraries := libart
-
-##
-## Build the device command line tool dexlayout.
-##
-
-ifneq ($(SDK_ONLY),true)  # SDK_only doesn't need device version
-include $(CLEAR_VARS)
-LOCAL_CPP_EXTENSION := cc
-LOCAL_SRC_FILES := $(dexlayout_src_files)
-LOCAL_C_INCLUDES := $(dexlayout_c_includes)
-LOCAL_CFLAGS += -Wall
-LOCAL_SHARED_LIBRARIES += $(dexlayout_libraries)
-LOCAL_MODULE := dexlayout
-include $(BUILD_EXECUTABLE)
-endif # !SDK_ONLY
-
-##
-## Build the host command line tool dexlayout.
-##
-
-include $(CLEAR_VARS)
-LOCAL_CPP_EXTENSION := cc
-LOCAL_SRC_FILES := $(dexlayout_src_files)
-LOCAL_C_INCLUDES := $(dexlayout_c_includes)
-LOCAL_CFLAGS += -Wall
-LOCAL_SHARED_LIBRARIES += $(dexlayout_libraries)
-LOCAL_MODULE := dexlayout
-LOCAL_MULTILIB := $(ART_MULTILIB_OVERRIDE_host)
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/dexlist/Android.bp b/dexlist/Android.bp
new file mode 100644
index 0000000..8e3c91d
--- /dev/null
+++ b/dexlist/Android.bp
@@ -0,0 +1,21 @@
+// 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.
+
+art_cc_binary {
+    name: "dexlist",
+    host_supported: true,
+    srcs: ["dexlist.cc"],
+    cflags: ["-Wall"],
+    shared_libs: ["libart"],
+}
diff --git a/dexlist/Android.mk b/dexlist/Android.mk
deleted file mode 100755
index 6ec6c97..0000000
--- a/dexlist/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# 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.
-
-# TODO(ajcbik): Art-i-fy this makefile
-
-LOCAL_PATH:= $(call my-dir)
-
-dexlist_src_files := dexlist.cc
-dexlist_c_includes := art/runtime
-dexlist_libraries := libart
-
-##
-## Build the device command line tool dexlist.
-##
-
-ifneq ($(SDK_ONLY),true)  # SDK_only doesn't need device version
-include $(CLEAR_VARS)
-LOCAL_CPP_EXTENSION := cc
-LOCAL_SRC_FILES := $(dexlist_src_files)
-LOCAL_C_INCLUDES := $(dexlist_c_includes)
-LOCAL_CFLAGS += -Wall
-LOCAL_SHARED_LIBRARIES += $(dexlist_libraries)
-LOCAL_MODULE := dexlist
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-include $(BUILD_EXECUTABLE)
-endif # !SDK_ONLY
-
-##
-## Build the host command line tool dexlist.
-##
-
-include $(CLEAR_VARS)
-LOCAL_CPP_EXTENSION := cc
-LOCAL_SRC_FILES := $(dexlist_src_files)
-LOCAL_C_INCLUDES := $(dexlist_c_includes)
-LOCAL_CFLAGS += -Wall
-LOCAL_SHARED_LIBRARIES += $(dexlist_libraries)
-LOCAL_MODULE := dexlist
-LOCAL_MULTILIB := $(ART_MULTILIB_OVERRIDE_host)
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/disassembler/Android.bp b/disassembler/Android.bp
new file mode 100644
index 0000000..d06e4de
--- /dev/null
+++ b/disassembler/Android.bp
@@ -0,0 +1,58 @@
+//
+// Copyright (C) 2012 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.
+//
+
+art_cc_defaults {
+    name: "libart-disassembler-defaults",
+    defaults: ["art_defaults"],
+    host_supported: true,
+    clang: true,
+    srcs: [
+        "disassembler.cc",
+        "disassembler_arm.cc",
+        "disassembler_arm64.cc",
+        "disassembler_mips.cc",
+        "disassembler_x86.cc",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libbase",
+    ],
+    export_include_dirs: ["."],
+}
+
+art_cc_library {
+    name: "libart-disassembler",
+    defaults: ["libart-disassembler-defaults"],
+    shared_libs: [
+        "libart",
+        // For disassembler_arm64.
+        "libvixld-arm64",
+    ],
+}
+
+art_cc_library {
+    name: "libartd-disassembler",
+    defaults: [
+        "libart-disassembler-defaults",
+        "art_debug_defaults",
+    ],
+    shared_libs: [
+        "libartd",
+        // For disassembler_arm64.
+        "libvixld-arm64",
+    ],
+}
diff --git a/disassembler/Android.mk b/disassembler/Android.mk
deleted file mode 100644
index 630f3e4..0000000
--- a/disassembler/Android.mk
+++ /dev/null
@@ -1,165 +0,0 @@
-#
-# Copyright (C) 2012 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include art/build/Android.common_build.mk
-
-LIBART_DISASSEMBLER_SRC_FILES := \
-	disassembler.cc \
-	disassembler_arm.cc \
-	disassembler_arm64.cc \
-	disassembler_mips.cc \
-	disassembler_x86.cc
-
-# $(1): target or host
-# $(2): ndebug or debug
-# $(3): static or shared (static is only valid for host)
-define build-libart-disassembler
-  ifneq ($(1),target)
-    ifneq ($(1),host)
-      $$(error expected target or host for argument 1, received $(1))
-    endif
-  endif
-  ifneq ($(2),ndebug)
-    ifneq ($(2),debug)
-      $$(error expected ndebug or debug for argument 2, received $(2))
-    endif
-  endif
-  ifeq ($(3),static)
-    ifneq ($(1),host)
-      $$(error received static for argument 3, but argument 1 is not host)
-    endif
-  else
-    ifneq ($(3),shared)
-      $$(error expected static or shared for argument 3, received $(3))
-    endif
-  endif
-
-  art_target_or_host := $(1)
-  art_ndebug_or_debug := $(2)
-  art_static_or_shared := $(3)
-
-  include $(CLEAR_VARS)
-  ifeq ($$(art_target_or_host),host)
-     LOCAL_IS_HOST_MODULE := true
-  endif
-  LOCAL_CPP_EXTENSION := $(ART_CPP_EXTENSION)
-  ifeq ($$(art_ndebug_or_debug),ndebug)
-    LOCAL_MODULE := libart-disassembler
-  else # debug
-    LOCAL_MODULE := libartd-disassembler
-  endif
-
-  LOCAL_MODULE_TAGS := optional
-  ifeq ($$(art_static_or_shared),static)
-    LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-  else # shared
-    LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-  endif
-
-  LOCAL_SRC_FILES := $$(LIBART_DISASSEMBLER_SRC_FILES)
-
-  ifeq ($$(art_target_or_host),target)
-    LOCAL_CLANG := $(ART_TARGET_CLANG)
-    $(call set-target-local-cflags-vars,$(2))
-  else # host
-    LOCAL_CLANG := $(ART_HOST_CLANG)
-    LOCAL_CFLAGS += $(ART_HOST_CFLAGS)
-    LOCAL_ASFLAGS += $(ART_HOST_ASFLAGS)
-    ifeq ($$(art_ndebug_or_debug),debug)
-      LOCAL_CFLAGS += $(ART_HOST_DEBUG_CFLAGS)
-      LOCAL_ASFLAGS += $(ART_HOST_DEBUG_ASFLAGS)
-    else
-      LOCAL_CFLAGS += $(ART_HOST_NON_DEBUG_CFLAGS)
-      LOCAL_ASFLAGS += $(ART_HOST_NON_DEBUG_ASFLAGS)
-    endif
-  endif
-
-  ifeq ($$(art_static_or_shared),static)
-    LOCAL_STATIC_LIBRARIES += liblog
-    ifeq ($$(art_ndebug_or_debug),debug)
-      LOCAL_STATIC_LIBRARIES += libartd
-    else
-      LOCAL_STATIC_LIBRARIES += libart
-    endif
-  else # shared
-    LOCAL_SHARED_LIBRARIES += liblog
-    ifeq ($$(art_ndebug_or_debug),debug)
-      LOCAL_SHARED_LIBRARIES += libartd
-    else
-      LOCAL_SHARED_LIBRARIES += libart
-    endif
-  endif
-
-  LOCAL_C_INCLUDES += $(ART_C_INCLUDES) art/runtime
-  LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
-  LOCAL_MULTILIB := both
-
-  LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
-  LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
-  LOCAL_NATIVE_COVERAGE := $(ART_COVERAGE)
-  # For disassembler_arm64.
-  ifeq ($$(art_static_or_shared),static)
-    ifeq ($$(art_ndebug_or_debug),debug)
-      LOCAL_STATIC_LIBRARIES += libvixld-arm64
-    else
-      LOCAL_STATIC_LIBRARIES += libvixl-arm64
-    endif
-    ifeq ($$(art_target_or_host),target)
-      $$(error libart-disassembler static builds for target are not supported)
-    else # host
-      include $(BUILD_HOST_STATIC_LIBRARY)
-    endif
-  else # shared
-    ifeq ($$(art_ndebug_or_debug),debug)
-      LOCAL_SHARED_LIBRARIES += libvixld-arm64
-    else
-      LOCAL_SHARED_LIBRARIES += libvixl-arm64
-    endif
-    ifeq ($$(art_target_or_host),target)
-      include $(BUILD_SHARED_LIBRARY)
-    else # host
-      include $(BUILD_HOST_SHARED_LIBRARY)
-    endif
-  endif
-
-  # Clear out local variables now that we're done with them.
-  art_target_or_host :=
-  art_ndebug_or_debug :=
-  art_static_or_shared :=
-endef
-
-ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
-  $(eval $(call build-libart-disassembler,target,ndebug,shared))
-endif
-ifeq ($(ART_BUILD_TARGET_DEBUG),true)
-  $(eval $(call build-libart-disassembler,target,debug,shared))
-endif
-# We always build dex2oat and dependencies, even if the host build is
-# otherwise disabled, since they are used to cross compile for the target.
-ifeq ($(ART_BUILD_HOST_NDEBUG),true)
-  $(eval $(call build-libart-disassembler,host,ndebug,shared))
-  ifeq ($(ART_BUILD_HOST_STATIC),true)
-    $(eval $(call build-libart-disassembler,host,ndebug,static))
-  endif
-endif
-ifeq ($(ART_BUILD_HOST_DEBUG),true)
-  $(eval $(call build-libart-disassembler,host,debug,shared))
-  ifeq ($(ART_BUILD_HOST_STATIC),true)
-    $(eval $(call build-libart-disassembler,host,debug,static))
-  endif
-endif
diff --git a/disassembler/disassembler.cc b/disassembler/disassembler.cc
index bcd0d16..8eecc62 100644
--- a/disassembler/disassembler.cc
+++ b/disassembler/disassembler.cc
@@ -18,15 +18,23 @@
 
 #include <ostream>
 
-#include "base/logging.h"
-#include "base/stringprintf.h"
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+
 #include "disassembler_arm.h"
 #include "disassembler_arm64.h"
 #include "disassembler_mips.h"
 #include "disassembler_x86.h"
 
+using android::base::StringPrintf;
+
 namespace art {
 
+Disassembler::Disassembler(DisassemblerOptions* disassembler_options)
+    : disassembler_options_(disassembler_options) {
+  CHECK(disassembler_options_ != nullptr);
+}
+
 Disassembler* Disassembler::Create(InstructionSet instruction_set, DisassemblerOptions* options) {
   if (instruction_set == kArm || instruction_set == kThumb2) {
     return new arm::DisassemblerArm(options);
@@ -39,7 +47,7 @@
   } else if (instruction_set == kX86_64) {
     return new x86::DisassemblerX86(options, true);
   } else {
-    UNIMPLEMENTED(FATAL) << "no disassembler for " << instruction_set;
+    UNIMPLEMENTED(FATAL) << static_cast<uint32_t>(instruction_set);
     return nullptr;
   }
 }
diff --git a/disassembler/disassembler.h b/disassembler/disassembler.h
index 86793cc..1ef456c 100644
--- a/disassembler/disassembler.h
+++ b/disassembler/disassembler.h
@@ -21,8 +21,9 @@
 
 #include <iosfwd>
 
+#include "android-base/macros.h"
+
 #include "arch/instruction_set.h"
-#include "base/macros.h"
 
 namespace art {
 
@@ -81,10 +82,7 @@
   }
 
  protected:
-  explicit Disassembler(DisassemblerOptions* disassembler_options)
-      : disassembler_options_(disassembler_options) {
-    CHECK(disassembler_options_ != nullptr);
-  }
+  explicit Disassembler(DisassemblerOptions* disassembler_options);
 
   std::string FormatInstructionPointer(const uint8_t* begin);
 
diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc
index a47b6ad..c3e288d 100644
--- a/disassembler/disassembler_arm.cc
+++ b/disassembler/disassembler_arm.cc
@@ -21,10 +21,13 @@
 #include <ostream>
 #include <sstream>
 
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+
 #include "arch/arm/registers_arm.h"
 #include "base/bit_utils.h"
-#include "base/logging.h"
-#include "base/stringprintf.h"
+
+using android::base::StringPrintf;
 
 namespace art {
 namespace arm {
diff --git a/disassembler/disassembler_arm64.cc b/disassembler/disassembler_arm64.cc
index 80bacb2..49b9623 100644
--- a/disassembler/disassembler_arm64.cc
+++ b/disassembler/disassembler_arm64.cc
@@ -20,8 +20,10 @@
 
 #include <sstream>
 
-#include "base/logging.h"
-#include "base/stringprintf.h"
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+
+using android::base::StringPrintf;
 
 using namespace vixl::aarch64;  // NOLINT(build/namespaces)
 
diff --git a/disassembler/disassembler_mips.cc b/disassembler/disassembler_mips.cc
index 02c6d71..9a73f29 100644
--- a/disassembler/disassembler_mips.cc
+++ b/disassembler/disassembler_mips.cc
@@ -19,8 +19,10 @@
 #include <ostream>
 #include <sstream>
 
-#include "base/logging.h"
-#include "base/stringprintf.h"
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+
+using android::base::StringPrintf;
 
 namespace art {
 namespace mips {
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index 2ca84e5..9f49ec6 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -21,8 +21,10 @@
 #include <ostream>
 #include <sstream>
 
-#include "base/logging.h"
-#include "base/stringprintf.h"
+#include "android-base/logging.h"
+#include "android-base/stringprintf.h"
+
+using android::base::StringPrintf;
 
 namespace art {
 namespace x86 {
diff --git a/oatdump/Android.bp b/oatdump/Android.bp
new file mode 100644
index 0000000..b01bf51
--- /dev/null
+++ b/oatdump/Android.bp
@@ -0,0 +1,89 @@
+//
+// Copyright (C) 2011 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.
+//
+
+cc_defaults {
+    name: "oatdump-defaults",
+    defaults: ["art_defaults"],
+    host_supported: true,
+    srcs: ["oatdump.cc"],
+    target: {
+        android: {
+            shared_libs: ["libcutils"],
+        },
+    },
+    include_dirs: ["art/cmdline"],
+}
+
+art_cc_binary {
+    name: "oatdump",
+    defaults: ["oatdump-defaults"],
+    shared_libs: [
+        "libart",
+        "libart-compiler",
+        "libart-disassembler",
+    ],
+}
+
+art_cc_binary {
+    name: "oatdumpd",
+    defaults: [
+        "art_debug_defaults",
+        "oatdump-defaults",
+    ],
+    shared_libs: [
+        "libartd",
+        "libartd-compiler",
+        "libartd-disassembler",
+    ],
+}
+
+art_cc_binary {
+    name: "oatdumps",
+    defaults: ["oatdump-defaults"],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    static_libs: [
+        "libart",
+        "libart-compiler",
+        "libart-disassembler",
+        "libvixl-arm",
+        "libvixl-arm64",
+    ] + art_static_dependencies,
+}
+
+art_cc_binary {
+    name: "oatdumpds",
+    defaults: [
+        "art_debug_defaults",
+        "oatdump-defaults",
+    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    static_libs: [
+        "libartd",
+        "libartd-compiler",
+        "libartd-disassembler",
+        "libvixld-arm",
+        "libvixld-arm64",
+    ] + art_static_dependencies,
+}
+
diff --git a/oatdump/Android.mk b/oatdump/Android.mk
index 4b37c6a..7be8a8d 100644
--- a/oatdump/Android.mk
+++ b/oatdump/Android.mk
@@ -16,41 +16,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-include art/build/Android.executable.mk
-
-OATDUMP_SRC_FILES := \
-	oatdump.cc
-
-# Build variants {target,host} x {debug,ndebug}
-$(eval $(call build-art-multi-executable,oatdump,$(OATDUMP_SRC_FILES),libart-compiler libart-disassembler,libcutils,,art/compiler art/disassembler))
-
-# Static variants (only for host).
-ifeq ($(ART_BUILD_HOST_STATIC),true)
-  ifeq ($(HOST_PREFER_32_BIT),true)
-    # We need to explicitly restrict the host arch to 32-bit only, as
-    # giving 'both' would make build-art-executable generate a build
-    # rule for a 64-bit oatdump executable too.
-    oatdump_host_arch := 32
-  else
-    oatdump_host_arch := both
-  endif
-
-  ifeq ($(ART_BUILD_HOST_NDEBUG),true)
-    $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),libart libart-compiler libart-disassembler libvixl-arm64 $(ART_STATIC_DEPENDENCIES),art/compiler art/disassembler,host,ndebug,$(oatdump_host_arch),static))
-  endif
-  ifeq ($(ART_BUILD_HOST_DEBUG),true)
-    $(eval $(call build-art-executable,oatdump,$(OATDUMP_SRC_FILES),libartd libartd-compiler libartd-disassembler libvixld-arm64 $(ART_STATIC_DEPENDENCIES),art/compiler art/disassembler,host,debug,$(oatdump_host_arch),static))
-  endif
-
-  # Clear locals now they've served their purpose.
-  oatdump_host_arch :=
-endif
-
-########################################################################
-# oatdump targets
-
-ART_DUMP_OAT_PATH ?= $(OUT_DIR)
-
 OATDUMP := $(HOST_OUT_EXECUTABLES)/oatdump$(HOST_EXECUTABLE_SUFFIX)
 OATDUMPD := $(HOST_OUT_EXECUTABLES)/oatdumpd$(HOST_EXECUTABLE_SUFFIX)
 # TODO: for now, override with debug version for better error reporting
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 22d79cb..59e4a15 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -97,7 +97,6 @@
         "intern_table.cc",
         "interpreter/interpreter.cc",
         "interpreter/interpreter_common.cc",
-        "interpreter/interpreter_goto_table_impl.cc",
         "interpreter/interpreter_switch_impl.cc",
         "interpreter/unstarted_runtime.cc",
         "java_vm_ext.cc",
diff --git a/runtime/arch/instruction_set.cc b/runtime/arch/instruction_set.cc
index b35e088..8f64dcd 100644
--- a/runtime/arch/instruction_set.cc
+++ b/runtime/arch/instruction_set.cc
@@ -19,11 +19,31 @@
 // Explicitly include our own elf.h to avoid Linux and other dependencies.
 #include "../elf.h"
 #include "base/bit_utils.h"
+#include "base/logging.h"
 #include "globals.h"
 
 namespace art {
 
-const char* GetInstructionSetString(const InstructionSet isa) {
+void InstructionSetAbort(InstructionSet isa) {
+  switch (isa) {
+    case kArm:
+    case kThumb2:
+    case kArm64:
+    case kX86:
+    case kX86_64:
+    case kMips:
+    case kMips64:
+    case kNone:
+      LOG(FATAL) << "Unsupported instruction set " << isa;
+      UNREACHABLE();
+
+    default:
+      LOG(FATAL) << "Unknown ISA " << isa;
+      UNREACHABLE();
+  }
+}
+
+const char* GetInstructionSetString(InstructionSet isa) {
   switch (isa) {
     case kArm:
     case kThumb2:
diff --git a/runtime/arch/instruction_set.h b/runtime/arch/instruction_set.h
index 917acc9..4a8bea4 100644
--- a/runtime/arch/instruction_set.h
+++ b/runtime/arch/instruction_set.h
@@ -21,7 +21,7 @@
 #include <string>
 
 #include "base/enums.h"
-#include "base/logging.h"  // Logging is required for FATAL in the helper functions.
+#include "base/macros.h"
 
 namespace art {
 
@@ -75,7 +75,6 @@
 // X86 instruction alignment. This is the recommended alignment for maximum performance.
 static constexpr size_t kX86Alignment = 16;
 
-
 const char* GetInstructionSetString(InstructionSet isa);
 
 // Note: Returns kNone when the string cannot be parsed to a known value.
@@ -83,6 +82,9 @@
 
 InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags);
 
+// Fatal logging out of line to keep the header clean of logging.h.
+NO_RETURN void InstructionSetAbort(InstructionSet isa);
+
 static inline PointerSize GetInstructionSetPointerSize(InstructionSet isa) {
   switch (isa) {
     case kArm:
@@ -99,12 +101,8 @@
       return kMipsPointerSize;
     case kMips64:
       return kMips64PointerSize;
-    case kNone:
-      LOG(FATAL) << "ISA kNone does not have pointer size.";
-      UNREACHABLE();
     default:
-      LOG(FATAL) << "Unknown ISA " << isa;
-      UNREACHABLE();
+      InstructionSetAbort(isa);
   }
 }
 
@@ -139,12 +137,8 @@
     case kMips64:
       return true;
 
-    case kNone:
-      LOG(FATAL) << "ISA kNone does not have bit width.";
-      UNREACHABLE();
     default:
-      LOG(FATAL) << "Unknown ISA " << isa;
-      UNREACHABLE();
+      InstructionSetAbort(isa);
   }
 }
 
@@ -168,12 +162,9 @@
       return 4;
     case kMips64:
       return 8;
-    case kNone:
-      LOG(FATAL) << "ISA kNone does not have spills.";
-      UNREACHABLE();
+
     default:
-      LOG(FATAL) << "Unknown ISA " << isa;
-      UNREACHABLE();
+      InstructionSetAbort(isa);
   }
 }
 
@@ -193,12 +184,9 @@
       return 4;
     case kMips64:
       return 8;
-    case kNone:
-      LOG(FATAL) << "ISA kNone does not have spills.";
-      UNREACHABLE();
+
     default:
-      LOG(FATAL) << "Unknown ISA " << isa;
-      UNREACHABLE();
+      InstructionSetAbort(isa);
   }
 }
 
diff --git a/runtime/arch/instruction_set_features_test.cc b/runtime/arch/instruction_set_features_test.cc
index fb38b47..7bbc709 100644
--- a/runtime/arch/instruction_set_features_test.cc
+++ b/runtime/arch/instruction_set_features_test.cc
@@ -22,6 +22,7 @@
 #include "cutils/properties.h"
 #endif
 
+#include "base/logging.h"
 #include "base/stringprintf.h"
 
 namespace art {
diff --git a/runtime/arch/mips/instruction_set_features_mips.h b/runtime/arch/mips/instruction_set_features_mips.h
index 120dc1c..2d54988 100644
--- a/runtime/arch/mips/instruction_set_features_mips.h
+++ b/runtime/arch/mips/instruction_set_features_mips.h
@@ -18,6 +18,8 @@
 #define ART_RUNTIME_ARCH_MIPS_INSTRUCTION_SET_FEATURES_MIPS_H_
 
 #include "arch/instruction_set_features.h"
+#include "base/logging.h"
+#include "base/macros.h"
 
 namespace art {
 
diff --git a/runtime/base/bit_utils.h b/runtime/base/bit_utils.h
index 378371d..d2f0fdb 100644
--- a/runtime/base/bit_utils.h
+++ b/runtime/base/bit_utils.h
@@ -21,7 +21,12 @@
 #include <limits>
 #include <type_traits>
 
+// This header is used in the disassembler with libbase's logging. Only include ART logging
+// when no other logging macros are available. b/15436106, b/31338270
+#ifndef CHECK
 #include "base/logging.h"
+#endif
+
 #include "base/iteration_range.h"
 #include "base/stl_util.h"
 
diff --git a/runtime/base/enums.h b/runtime/base/enums.h
index 51b86ea..52cab2a 100644
--- a/runtime/base/enums.h
+++ b/runtime/base/enums.h
@@ -20,9 +20,6 @@
 #include <cstddef>
 #include <ostream>
 
-#include "base/logging.h"
-#include "base/macros.h"
-
 namespace art {
 
 enum class PointerSize : size_t {
@@ -35,16 +32,6 @@
                                                        ? PointerSize::k64
                                                        : PointerSize::k32;
 
-template <typename T>
-static constexpr PointerSize ConvertToPointerSize(T any) {
-  if (any == 4 || any == 8) {
-    return static_cast<PointerSize>(any);
-  } else {
-    LOG(FATAL);
-    UNREACHABLE();
-  }
-}
-
 }  // namespace art
 
 #endif  // ART_RUNTIME_BASE_ENUMS_H_
diff --git a/runtime/base/stl_util.h b/runtime/base/stl_util.h
index a53dcea..a4cf249 100644
--- a/runtime/base/stl_util.h
+++ b/runtime/base/stl_util.h
@@ -20,7 +20,11 @@
 #include <algorithm>
 #include <sstream>
 
+// This header is used in the disassembler with libbase's logging. Only include ART logging
+// when no other logging macros are available. b/15436106, b/31338270
+#ifndef CHECK
 #include "base/logging.h"
+#endif
 
 namespace art {
 
diff --git a/runtime/code_simulator_container.h b/runtime/code_simulator_container.h
index 655a247..10178ba 100644
--- a/runtime/code_simulator_container.h
+++ b/runtime/code_simulator_container.h
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_CODE_SIMULATOR_CONTAINER_H_
 
 #include "arch/instruction_set.h"
+#include "base/logging.h"
 #include "simulator/code_simulator.h"
 
 namespace art {
diff --git a/runtime/image.cc b/runtime/image.cc
index 6888183..7e6790a 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -20,6 +20,7 @@
 #include "mirror/object_array.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
+#include "utils.h"
 
 namespace art {
 
@@ -179,4 +180,8 @@
   }
 }
 
+PointerSize ImageHeader::GetPointerSize() const {
+  return ConvertToPointerSize(pointer_size_);
+}
+
 }  // namespace art
diff --git a/runtime/image.h b/runtime/image.h
index 8cd94bb..3a4fa79 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -157,9 +157,7 @@
     return reinterpret_cast<uint8_t*>(oat_file_end_);
   }
 
-  PointerSize GetPointerSize() const {
-    return ConvertToPointerSize(pointer_size_);
-  }
+  PointerSize GetPointerSize() const;
 
   uint32_t GetPointerSizeUnchecked() const {
     return pointer_size_;
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 277bda4..0003e72 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -20,7 +20,6 @@
 
 #include "common_throws.h"
 #include "interpreter_common.h"
-#include "interpreter_goto_table_impl.h"
 #include "interpreter_mterp_impl.h"
 #include "interpreter_switch_impl.h"
 #include "mirror/string-inl.h"
@@ -231,15 +230,12 @@
 
 enum InterpreterImplKind {
   kSwitchImplKind,        // Switch-based interpreter implementation.
-  kComputedGotoImplKind,  // Computed-goto-based interpreter implementation.
   kMterpImplKind          // Assembly interpreter
 };
 static std::ostream& operator<<(std::ostream& os, const InterpreterImplKind& rhs) {
   os << ((rhs == kSwitchImplKind)
               ? "Switch-based interpreter"
-              : (rhs == kComputedGotoImplKind)
-                  ? "Computed-goto-based interpreter"
-                  : "Asm interpreter");
+              : "Asm interpreter");
   return os;
 }
 
@@ -323,7 +319,8 @@
           }
         }
       }
-    } else if (kInterpreterImplKind == kSwitchImplKind) {
+    } else {
+      DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind);
       if (transaction_active) {
         return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register,
                                               false);
@@ -331,13 +328,6 @@
         return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register,
                                                false);
       }
-    } else {
-      DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
-      if (transaction_active) {
-        return ExecuteGotoImpl<false, true>(self, code_item, shadow_frame, result_register);
-      } else {
-        return ExecuteGotoImpl<false, false>(self, code_item, shadow_frame, result_register);
-      }
     }
   } else {
     // Enter the "with access check" interpreter.
@@ -350,7 +340,8 @@
         return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register,
                                               false);
       }
-    } else if (kInterpreterImplKind == kSwitchImplKind) {
+    } else {
+      DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind);
       if (transaction_active) {
         return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register,
                                              false);
@@ -358,13 +349,6 @@
         return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register,
                                               false);
       }
-    } else {
-      DCHECK_EQ(kInterpreterImplKind, kComputedGotoImplKind);
-      if (transaction_active) {
-        return ExecuteGotoImpl<true, true>(self, code_item, shadow_frame, result_register);
-      } else {
-        return ExecuteGotoImpl<true, false>(self, code_item, shadow_frame, result_register);
-      }
     }
   }
 }
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
deleted file mode 100644
index 37dd63b..0000000
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ /dev/null
@@ -1,2607 +0,0 @@
-/*
- * Copyright (C) 2012 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 "interpreter_goto_table_impl.h"
-
-// Common includes
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/mutex.h"
-#include "stack.h"
-#include "thread.h"
-
-// Clang compiles the GOTO interpreter very slowly. So we skip it. These are the implementation
-// details only necessary when compiling it.
-#if !defined(__clang__)
-#include "experimental_flags.h"
-#include "interpreter_common.h"
-#include "jit/jit.h"
-#include "safe_math.h"
-#endif
-
-namespace art {
-namespace interpreter {
-
-#if !defined(__clang__)
-
-// In the following macros, we expect the following local variables exist:
-// - "self": the current Thread*.
-// - "inst" : the current Instruction*.
-// - "inst_data" : the current instruction's first 16 bits.
-// - "dex_pc": the current pc.
-// - "shadow_frame": the current shadow frame.
-// - "currentHandlersTable": the current table of pointer to each instruction handler.
-
-// Advance to the next instruction and updates interpreter state.
-#define ADVANCE(_offset)                                                    \
-  do {                                                                      \
-    int32_t disp = static_cast<int32_t>(_offset);                           \
-    inst = inst->RelativeAt(disp);                                          \
-    dex_pc = static_cast<uint32_t>(static_cast<int32_t>(dex_pc) + disp);    \
-    shadow_frame.SetDexPC(dex_pc);                                          \
-    TraceExecution(shadow_frame, inst, dex_pc);                             \
-    inst_data = inst->Fetch16(0);                                           \
-    goto *currentHandlersTable[inst->Opcode(inst_data)];                    \
-  } while (false)
-
-#define HANDLE_PENDING_EXCEPTION() goto exception_pending_label
-
-#define POSSIBLY_HANDLE_PENDING_EXCEPTION(_is_exception_pending, _offset)   \
-  do {                                                                      \
-    if (UNLIKELY(_is_exception_pending)) {                                  \
-      HANDLE_PENDING_EXCEPTION();                                           \
-    } else {                                                                \
-      ADVANCE(_offset);                                                     \
-    }                                                                       \
-  } while (false)
-
-#define UPDATE_HANDLER_TABLE() \
-  currentHandlersTable = handlersTable[ \
-      Runtime::Current()->GetInstrumentation()->GetInterpreterHandlerTable()]
-
-#define BRANCH_INSTRUMENTATION(offset)                                                          \
-  do {                                                                                          \
-    if (UNLIKELY(instrumentation->HasBranchListeners())) {                                      \
-      instrumentation->Branch(self, method, dex_pc, offset);                                    \
-    }                                                                                           \
-    JValue result;                                                                              \
-    if (jit::Jit::MaybeDoOnStackReplacement(self, method, dex_pc, offset, &result)) {           \
-      return result;                                                                            \
-    }                                                                                           \
-  } while (false)
-
-#define HOTNESS_UPDATE()                                                                       \
-  do {                                                                                         \
-    if (jit != nullptr) {                                                                      \
-      jit->AddSamples(self, method, 1, /*with_backedges*/ true);                               \
-    }                                                                                          \
-  } while (false)
-
-#define UNREACHABLE_CODE_CHECK()                \
-  do {                                          \
-    if (kIsDebugBuild) {                        \
-      LOG(FATAL) << "We should not be here !";  \
-      UNREACHABLE();                            \
-    }                                           \
-  } while (false)
-
-#define HANDLE_INSTRUCTION_START(opcode) op_##opcode:  // NOLINT(whitespace/labels)
-#define HANDLE_INSTRUCTION_END() UNREACHABLE_CODE_CHECK()
-
-#define HANDLE_MONITOR_CHECKS()                                                                   \
-  if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {                       \
-    HANDLE_PENDING_EXCEPTION();                                                                   \
-  }
-
-/**
- * Interpreter based on computed goto tables.
- *
- * Each instruction is associated to a handler. This handler is responsible for executing the
- * instruction and jump to the next instruction's handler.
- * In order to limit the cost of instrumentation, we have two handler tables:
- * - the "main" handler table: it contains handlers for normal execution of each instruction without
- * handling of instrumentation.
- * - the "alternative" handler table: it contains alternative handlers which first handle
- * instrumentation before jumping to the corresponding "normal" instruction's handler.
- *
- * When instrumentation is active, the interpreter uses the "alternative" handler table. Otherwise
- * it uses the "main" handler table.
- *
- * The current handler table is the handler table being used by the interpreter. It is updated:
- * - on backward branch (goto, if and switch instructions)
- * - after invoke
- * - when an exception is thrown.
- * This allows to support an attaching debugger to an already running application for instance.
- *
- * For a fast handler table update, handler tables are stored in an array of handler tables. Each
- * handler table is represented by the InterpreterHandlerTable enum which allows to associate it
- * to an index in this array of handler tables ((see Instrumentation::GetInterpreterHandlerTable).
- *
- * Here's the current layout of this array of handler tables:
- *
- * ---------------------+---------------+
- *                      |     NOP       | (handler for NOP instruction)
- *                      +---------------+
- *       "main"         |     MOVE      | (handler for MOVE instruction)
- *    handler table     +---------------+
- *                      |      ...      |
- *                      +---------------+
- *                      |   UNUSED_FF   | (handler for UNUSED_FF instruction)
- * ---------------------+---------------+
- *                      |     NOP       | (alternative handler for NOP instruction)
- *                      +---------------+
- *    "alternative"     |     MOVE      | (alternative handler for MOVE instruction)
- *    handler table     +---------------+
- *                      |      ...      |
- *                      +---------------+
- *                      |   UNUSED_FF   | (alternative handler for UNUSED_FF instruction)
- * ---------------------+---------------+
- *
- */
-template<bool do_access_check, bool transaction_active>
-JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowFrame& shadow_frame,
-                       JValue result_register) {
-  // Define handler tables:
-  // - The main handler table contains execution handlers for each instruction.
-  // - The alternative handler table contains prelude handlers which check for thread suspend and
-  //   manage instrumentation before jumping to the execution handler.
-  static const void* const handlersTable[instrumentation::kNumHandlerTables][kNumPackedOpcodes] = {
-    {
-    // Main handler table.
-#define INSTRUCTION_HANDLER(o, code, n, f, i, a, v) &&op_##code,
-#include "dex_instruction_list.h"
-      DEX_INSTRUCTION_LIST(INSTRUCTION_HANDLER)
-#undef DEX_INSTRUCTION_LIST
-#undef INSTRUCTION_HANDLER
-    }, {
-    // Alternative handler table.
-#define INSTRUCTION_HANDLER(o, code, n, f, i, a, v) &&alt_op_##code,
-#include "dex_instruction_list.h"
-      DEX_INSTRUCTION_LIST(INSTRUCTION_HANDLER)
-#undef DEX_INSTRUCTION_LIST
-#undef INSTRUCTION_HANDLER
-    }
-  };
-
-  constexpr bool do_assignability_check = do_access_check;
-  if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
-    LOG(FATAL) << "Invalid shadow frame for interpreter use";
-    return JValue();
-  }
-  self->VerifyStack();
-
-  uint32_t dex_pc = shadow_frame.GetDexPC();
-  const Instruction* inst = Instruction::At(code_item->insns_ + dex_pc);
-  uint16_t inst_data;
-  const void* const* currentHandlersTable;
-  UPDATE_HANDLER_TABLE();
-  const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
-  ArtMethod* method = shadow_frame.GetMethod();
-  jit::Jit* jit = Runtime::Current()->GetJit();
-
-  // Jump to first instruction.
-  ADVANCE(0);
-  UNREACHABLE_CODE_CHECK();
-
-  HANDLE_INSTRUCTION_START(NOP)
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE)
-    shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_FROM16)
-    shadow_frame.SetVReg(inst->VRegA_22x(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_16)
-    shadow_frame.SetVReg(inst->VRegA_32x(),
-                         shadow_frame.GetVReg(inst->VRegB_32x()));
-    ADVANCE(3);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_WIDE)
-    shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
-                             shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_WIDE_FROM16)
-    shadow_frame.SetVRegLong(inst->VRegA_22x(inst_data),
-                             shadow_frame.GetVRegLong(inst->VRegB_22x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_WIDE_16)
-    shadow_frame.SetVRegLong(inst->VRegA_32x(),
-                             shadow_frame.GetVRegLong(inst->VRegB_32x()));
-    ADVANCE(3);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_OBJECT)
-    shadow_frame.SetVRegReference(inst->VRegA_12x(inst_data),
-                                  shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_OBJECT_FROM16)
-    shadow_frame.SetVRegReference(inst->VRegA_22x(inst_data),
-                                  shadow_frame.GetVRegReference(inst->VRegB_22x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_OBJECT_16)
-    shadow_frame.SetVRegReference(inst->VRegA_32x(),
-                                  shadow_frame.GetVRegReference(inst->VRegB_32x()));
-    ADVANCE(3);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_RESULT)
-    shadow_frame.SetVReg(inst->VRegA_11x(inst_data), result_register.GetI());
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_RESULT_WIDE)
-    shadow_frame.SetVRegLong(inst->VRegA_11x(inst_data), result_register.GetJ());
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_RESULT_OBJECT)
-    shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), result_register.GetL());
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MOVE_EXCEPTION) {
-    Throwable* exception = self->GetException();
-    DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
-    shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), exception);
-    self->ClearException();
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(RETURN_VOID_NO_BARRIER) {
-    JValue result;
-    self->AllowThreadSuspension();
-    HANDLE_MONITOR_CHECKS();
-    if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
-      instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
-                                       shadow_frame.GetMethod(), dex_pc,
-                                       result);
-    }
-    return result;
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(RETURN_VOID) {
-    QuasiAtomic::ThreadFenceForConstructor();
-    JValue result;
-    self->AllowThreadSuspension();
-    HANDLE_MONITOR_CHECKS();
-    if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
-      instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
-                                       shadow_frame.GetMethod(), dex_pc,
-                                       result);
-    }
-    return result;
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(RETURN) {
-    JValue result;
-    result.SetJ(0);
-    result.SetI(shadow_frame.GetVReg(inst->VRegA_11x(inst_data)));
-    self->AllowThreadSuspension();
-    HANDLE_MONITOR_CHECKS();
-    if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
-      instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
-                                       shadow_frame.GetMethod(), dex_pc,
-                                       result);
-    }
-    return result;
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(RETURN_WIDE) {
-    JValue result;
-    result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x(inst_data)));
-    self->AllowThreadSuspension();
-    HANDLE_MONITOR_CHECKS();
-    if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
-      instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
-                                       shadow_frame.GetMethod(), dex_pc,
-                                       result);
-    }
-    return result;
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(RETURN_OBJECT) {
-    JValue result;
-    self->AllowThreadSuspension();
-    HANDLE_MONITOR_CHECKS();
-    const uint8_t vreg_index = inst->VRegA_11x(inst_data);
-    Object* obj_result = shadow_frame.GetVRegReference(vreg_index);
-    if (do_assignability_check && obj_result != nullptr) {
-      size_t pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
-      Class* return_type = shadow_frame.GetMethod()->GetReturnType(true /* resolve */,
-                                                                   pointer_size);
-      obj_result = shadow_frame.GetVRegReference(vreg_index);
-      if (return_type == nullptr) {
-        // Return the pending exception.
-        HANDLE_PENDING_EXCEPTION();
-      }
-      if (!obj_result->VerifierInstanceOf(return_type)) {
-        // This should never happen.
-        std::string temp1, temp2;
-        self->ThrowNewExceptionF("Ljava/lang/VirtualMachineError;",
-                                 "Returning '%s' that is not instance of return type '%s'",
-                                 obj_result->GetClass()->GetDescriptor(&temp1),
-                                 return_type->GetDescriptor(&temp2));
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-    result.SetL(obj_result);
-    if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
-      instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
-                                       shadow_frame.GetMethod(), dex_pc,
-                                       result);
-    }
-    return result;
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST_4) {
-    uint32_t dst = inst->VRegA_11n(inst_data);
-    int32_t val = inst->VRegB_11n(inst_data);
-    shadow_frame.SetVReg(dst, val);
-    if (val == 0) {
-      shadow_frame.SetVRegReference(dst, nullptr);
-    }
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST_16) {
-    uint32_t dst = inst->VRegA_21s(inst_data);
-    int32_t val = inst->VRegB_21s();
-    shadow_frame.SetVReg(dst, val);
-    if (val == 0) {
-      shadow_frame.SetVRegReference(dst, nullptr);
-    }
-    ADVANCE(2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST) {
-    uint32_t dst = inst->VRegA_31i(inst_data);
-    int32_t val = inst->VRegB_31i();
-    shadow_frame.SetVReg(dst, val);
-    if (val == 0) {
-      shadow_frame.SetVRegReference(dst, nullptr);
-    }
-    ADVANCE(3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST_HIGH16) {
-    uint32_t dst = inst->VRegA_21h(inst_data);
-    int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16);
-    shadow_frame.SetVReg(dst, val);
-    if (val == 0) {
-      shadow_frame.SetVRegReference(dst, nullptr);
-    }
-    ADVANCE(2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST_WIDE_16)
-    shadow_frame.SetVRegLong(inst->VRegA_21s(inst_data), inst->VRegB_21s());
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST_WIDE_32)
-    shadow_frame.SetVRegLong(inst->VRegA_31i(inst_data), inst->VRegB_31i());
-    ADVANCE(3);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST_WIDE)
-    shadow_frame.SetVRegLong(inst->VRegA_51l(inst_data), inst->VRegB_51l());
-    ADVANCE(5);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST_WIDE_HIGH16)
-    shadow_frame.SetVRegLong(inst->VRegA_21h(inst_data),
-                             static_cast<uint64_t>(inst->VRegB_21h()) << 48);
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST_STRING) {
-    String* s = ResolveString(self, shadow_frame, inst->VRegB_21c());
-    if (UNLIKELY(s == nullptr)) {
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), s);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST_STRING_JUMBO) {
-    String* s = ResolveString(self, shadow_frame, inst->VRegB_31c());
-    if (UNLIKELY(s == nullptr)) {
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      shadow_frame.SetVRegReference(inst->VRegA_31c(inst_data), s);
-      ADVANCE(3);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CONST_CLASS) {
-    Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame.GetMethod(),
-                                      self, false, do_access_check);
-    if (UNLIKELY(c == nullptr)) {
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), c);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MONITOR_ENTER) {
-    Object* obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
-    if (UNLIKELY(obj == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      DoMonitorEnter<do_access_check>(self, &shadow_frame, obj);
-      POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), 1);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MONITOR_EXIT) {
-    Object* obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
-    if (UNLIKELY(obj == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      DoMonitorExit<do_access_check>(self, &shadow_frame, obj);
-      POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), 1);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CHECK_CAST) {
-    Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame.GetMethod(),
-                                      self, false, do_access_check);
-    if (UNLIKELY(c == nullptr)) {
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      Object* obj = shadow_frame.GetVRegReference(inst->VRegA_21c(inst_data));
-      if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
-        ThrowClassCastException(c, obj->GetClass());
-        HANDLE_PENDING_EXCEPTION();
-      } else {
-        ADVANCE(2);
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INSTANCE_OF) {
-    Class* c = ResolveVerifyAndClinit(inst->VRegC_22c(), shadow_frame.GetMethod(),
-                                      self, false, do_access_check);
-    if (UNLIKELY(c == nullptr)) {
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
-      shadow_frame.SetVReg(inst->VRegA_22c(inst_data), (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ARRAY_LENGTH) {
-    Object* array = shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data));
-    if (UNLIKELY(array == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      shadow_frame.SetVReg(inst->VRegA_12x(inst_data), array->AsArray()->GetLength());
-      ADVANCE(1);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(NEW_INSTANCE) {
-    Object* obj = nullptr;
-    Class* c = ResolveVerifyAndClinit(inst->VRegB_21c(), shadow_frame.GetMethod(),
-                                      self, false, do_access_check);
-    if (LIKELY(c != nullptr)) {
-      if (UNLIKELY(c->IsStringClass())) {
-        gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
-        obj = mirror::String::AllocEmptyString<true>(self, allocator_type);
-      } else {
-        obj = AllocObjectFromCode<do_access_check, true>(
-            inst->VRegB_21c(), shadow_frame.GetMethod(), self,
-            Runtime::Current()->GetHeap()->GetCurrentAllocator());
-      }
-    }
-    if (UNLIKELY(obj == nullptr)) {
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      obj->GetClass()->AssertInitializedOrInitializingInThread(self);
-      // Don't allow finalizable objects to be allocated during a transaction since these can't be
-      // finalized without a started runtime.
-      if (transaction_active && obj->GetClass()->IsFinalizable()) {
-        AbortTransactionF(self, "Allocating finalizable object in transaction: %s",
-                          PrettyTypeOf(obj).c_str());
-        HANDLE_PENDING_EXCEPTION();
-      }
-      shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), obj);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(NEW_ARRAY) {
-    int32_t length = shadow_frame.GetVReg(inst->VRegB_22c(inst_data));
-    Object* obj = AllocArrayFromCode<do_access_check, true>(
-        inst->VRegC_22c(), length, shadow_frame.GetMethod(), self,
-        Runtime::Current()->GetHeap()->GetCurrentAllocator());
-    if (UNLIKELY(obj == nullptr)) {
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      shadow_frame.SetVRegReference(inst->VRegA_22c(inst_data), obj);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(FILLED_NEW_ARRAY) {
-    bool success =
-        DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame,
-                                                                     self, &result_register);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(FILLED_NEW_ARRAY_RANGE) {
-    bool success =
-        DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
-                                                                    self, &result_register);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(FILL_ARRAY_DATA) {
-    Object* obj = shadow_frame.GetVRegReference(inst->VRegA_31t(inst_data));
-    const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
-    const Instruction::ArrayDataPayload* payload =
-        reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
-    bool success = FillArrayData(obj, payload);
-    if (transaction_active && success) {
-      RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
-    }
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(THROW) {
-    Object* exception = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
-    if (UNLIKELY(exception == nullptr)) {
-      ThrowNullPointerException("throw with null exception");
-    } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
-      // This should never happen.
-      std::string temp;
-      self->ThrowNewExceptionF("Ljava/lang/VirtualMachineError;",
-                               "Throwing '%s' that is not instance of Throwable",
-                               exception->GetClass()->GetDescriptor(&temp));
-    } else {
-      self->SetException(exception->AsThrowable());
-    }
-    HANDLE_PENDING_EXCEPTION();
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(GOTO) {
-    int8_t offset = inst->VRegA_10t(inst_data);
-    BRANCH_INSTRUMENTATION(offset);
-    if (IsBackwardBranch(offset)) {
-      HOTNESS_UPDATE();
-      if (UNLIKELY(self->TestAllFlags())) {
-        self->CheckSuspend();
-        UPDATE_HANDLER_TABLE();
-      }
-    }
-    ADVANCE(offset);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(GOTO_16) {
-    int16_t offset = inst->VRegA_20t();
-    BRANCH_INSTRUMENTATION(offset);
-    if (IsBackwardBranch(offset)) {
-      HOTNESS_UPDATE();
-      if (UNLIKELY(self->TestAllFlags())) {
-        self->CheckSuspend();
-        UPDATE_HANDLER_TABLE();
-      }
-    }
-    ADVANCE(offset);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(GOTO_32) {
-    int32_t offset = inst->VRegA_30t();
-    BRANCH_INSTRUMENTATION(offset);
-    if (IsBackwardBranch(offset)) {
-      HOTNESS_UPDATE();
-      if (UNLIKELY(self->TestAllFlags())) {
-        self->CheckSuspend();
-        UPDATE_HANDLER_TABLE();
-      }
-    }
-    ADVANCE(offset);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(PACKED_SWITCH) {
-    int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
-    BRANCH_INSTRUMENTATION(offset);
-    if (IsBackwardBranch(offset)) {
-      HOTNESS_UPDATE();
-      if (UNLIKELY(self->TestAllFlags())) {
-        self->CheckSuspend();
-        UPDATE_HANDLER_TABLE();
-      }
-    }
-    ADVANCE(offset);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SPARSE_SWITCH) {
-    int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
-    BRANCH_INSTRUMENTATION(offset);
-    if (IsBackwardBranch(offset)) {
-      HOTNESS_UPDATE();
-      if (UNLIKELY(self->TestAllFlags())) {
-        self->CheckSuspend();
-        UPDATE_HANDLER_TABLE();
-      }
-    }
-    ADVANCE(offset);
-  }
-  HANDLE_INSTRUCTION_END();
-
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wfloat-equal"
-#endif
-
-  HANDLE_INSTRUCTION_START(CMPL_FLOAT) {
-    float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
-    float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
-    int32_t result;
-    if (val1 > val2) {
-      result = 1;
-    } else if (val1 == val2) {
-      result = 0;
-    } else {
-      result = -1;
-    }
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
-    ADVANCE(2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CMPG_FLOAT) {
-    float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
-    float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
-    int32_t result;
-    if (val1 < val2) {
-      result = -1;
-    } else if (val1 == val2) {
-      result = 0;
-    } else {
-      result = 1;
-    }
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
-    ADVANCE(2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CMPL_DOUBLE) {
-    double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
-    double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
-    int32_t result;
-    if (val1 > val2) {
-      result = 1;
-    } else if (val1 == val2) {
-      result = 0;
-    } else {
-      result = -1;
-    }
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
-    ADVANCE(2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(CMPG_DOUBLE) {
-    double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
-    double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
-    int32_t result;
-    if (val1 < val2) {
-      result = -1;
-    } else if (val1 == val2) {
-      result = 0;
-    } else {
-      result = 1;
-    }
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
-    ADVANCE(2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
-  HANDLE_INSTRUCTION_START(CMP_LONG) {
-    int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
-    int64_t val2 = shadow_frame.GetVRegLong(inst->VRegC_23x());
-    int32_t result;
-    if (val1 > val2) {
-      result = 1;
-    } else if (val1 == val2) {
-      result = 0;
-    } else {
-      result = -1;
-    }
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
-    ADVANCE(2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_EQ) {
-    if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) == shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
-      int16_t offset = inst->VRegC_22t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_NE) {
-    if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) !=
-        shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
-      int16_t offset = inst->VRegC_22t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_LT) {
-    if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <
-        shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
-      int16_t offset = inst->VRegC_22t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_GE) {
-    if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >=
-        shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
-      int16_t offset = inst->VRegC_22t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_GT) {
-    if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >
-    shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
-      int16_t offset = inst->VRegC_22t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_LE) {
-    if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <=
-        shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
-      int16_t offset = inst->VRegC_22t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_EQZ) {
-    if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) == 0) {
-      int16_t offset = inst->VRegB_21t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_NEZ) {
-    if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) != 0) {
-      int16_t offset = inst->VRegB_21t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_LTZ) {
-    if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) < 0) {
-      int16_t offset = inst->VRegB_21t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_GEZ) {
-    if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) >= 0) {
-      int16_t offset = inst->VRegB_21t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_GTZ) {
-    if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) > 0) {
-      int16_t offset = inst->VRegB_21t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IF_LEZ)  {
-    if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) <= 0) {
-      int16_t offset = inst->VRegB_21t();
-      BRANCH_INSTRUMENTATION(offset);
-      if (IsBackwardBranch(offset)) {
-        HOTNESS_UPDATE();
-        if (UNLIKELY(self->TestAllFlags())) {
-          self->CheckSuspend();
-          UPDATE_HANDLER_TABLE();
-        }
-      }
-      ADVANCE(offset);
-    } else {
-      BRANCH_INSTRUMENTATION(2);
-      ADVANCE(2);
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AGET_BOOLEAN) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      BooleanArray* array = a->AsBooleanArray();
-      if (LIKELY(array->CheckIsValidIndex(index))) {
-        shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
-        ADVANCE(2);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AGET_BYTE) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      ByteArray* array = a->AsByteArray();
-      if (LIKELY(array->CheckIsValidIndex(index))) {
-        shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
-        ADVANCE(2);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AGET_CHAR) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      CharArray* array = a->AsCharArray();
-      if (LIKELY(array->CheckIsValidIndex(index))) {
-        shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
-        ADVANCE(2);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AGET_SHORT) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      ShortArray* array = a->AsShortArray();
-      if (LIKELY(array->CheckIsValidIndex(index))) {
-        shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
-        ADVANCE(2);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AGET) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      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);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AGET_WIDE)  {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      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);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AGET_OBJECT) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      ObjectArray<Object>* array = a->AsObjectArray<Object>();
-      if (LIKELY(array->CheckIsValidIndex(index))) {
-        shadow_frame.SetVRegReference(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
-        ADVANCE(2);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(APUT_BOOLEAN) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      uint8_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      BooleanArray* array = a->AsBooleanArray();
-      if (LIKELY(array->CheckIsValidIndex(index))) {
-        array->SetWithoutChecks<transaction_active>(index, val);
-        ADVANCE(2);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(APUT_BYTE) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int8_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      ByteArray* array = a->AsByteArray();
-      if (LIKELY(array->CheckIsValidIndex(index))) {
-        array->SetWithoutChecks<transaction_active>(index, val);
-        ADVANCE(2);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(APUT_CHAR) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      uint16_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      CharArray* array = a->AsCharArray();
-      if (LIKELY(array->CheckIsValidIndex(index))) {
-        array->SetWithoutChecks<transaction_active>(index, val);
-        ADVANCE(2);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(APUT_SHORT) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int16_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      ShortArray* array = a->AsShortArray();
-      if (LIKELY(array->CheckIsValidIndex(index))) {
-        array->SetWithoutChecks<transaction_active>(index, val);
-        ADVANCE(2);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(APUT) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int32_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      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);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(APUT_WIDE) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int64_t val = shadow_frame.GetVRegLong(inst->VRegA_23x(inst_data));
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      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);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(APUT_OBJECT) {
-    Object* a = shadow_frame.GetVRegReference(inst->VRegB_23x());
-    if (UNLIKELY(a == nullptr)) {
-      ThrowNullPointerExceptionFromInterpreter();
-      HANDLE_PENDING_EXCEPTION();
-    } else {
-      int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
-      Object* val = shadow_frame.GetVRegReference(inst->VRegA_23x(inst_data));
-      ObjectArray<Object>* array = a->AsObjectArray<Object>();
-      if (LIKELY(array->CheckIsValidIndex(index) && array->CheckAssignable(val))) {
-        array->SetWithoutChecks<transaction_active>(index, val);
-        ADVANCE(2);
-      } else {
-        HANDLE_PENDING_EXCEPTION();
-      }
-    }
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_BOOLEAN) {
-    bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimBoolean, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_BYTE) {
-    bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimByte, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_CHAR) {
-    bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimChar, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_SHORT) {
-    bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimShort, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET) {
-    bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimInt, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_WIDE) {
-    bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimLong, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_OBJECT) {
-    bool success = DoFieldGet<InstanceObjectRead, Primitive::kPrimNot, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_QUICK) {
-    bool success = DoIGetQuick<Primitive::kPrimInt>(shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_BOOLEAN_QUICK) {
-    bool success = DoIGetQuick<Primitive::kPrimBoolean>(shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_BYTE_QUICK) {
-    bool success = DoIGetQuick<Primitive::kPrimByte>(shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_CHAR_QUICK) {
-    bool success = DoIGetQuick<Primitive::kPrimChar>(shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_SHORT_QUICK) {
-    bool success = DoIGetQuick<Primitive::kPrimShort>(shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_WIDE_QUICK) {
-    bool success = DoIGetQuick<Primitive::kPrimLong>(shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IGET_OBJECT_QUICK) {
-    bool success = DoIGetQuick<Primitive::kPrimNot>(shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SGET_BOOLEAN) {
-    bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimBoolean, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SGET_BYTE) {
-    bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimByte, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SGET_CHAR) {
-    bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimChar, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SGET_SHORT) {
-    bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimShort, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SGET) {
-    bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimInt, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SGET_WIDE) {
-    bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimLong, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SGET_OBJECT) {
-    bool success = DoFieldGet<StaticObjectRead, Primitive::kPrimNot, do_access_check>(
-        self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_BOOLEAN) {
-    bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_BYTE) {
-    bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimByte, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_CHAR) {
-    bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimChar, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_SHORT) {
-    bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimShort, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT) {
-    bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimInt, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_WIDE) {
-    bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimLong, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_OBJECT) {
-    bool success = DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_QUICK) {
-    bool success = DoIPutQuick<Primitive::kPrimInt, transaction_active>(
-        shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_BOOLEAN_QUICK) {
-    bool success = DoIPutQuick<Primitive::kPrimBoolean, transaction_active>(
-        shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_BYTE_QUICK) {
-    bool success = DoIPutQuick<Primitive::kPrimByte, transaction_active>(
-        shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_CHAR_QUICK) {
-    bool success = DoIPutQuick<Primitive::kPrimChar, transaction_active>(
-        shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_SHORT_QUICK) {
-    bool success = DoIPutQuick<Primitive::kPrimShort, transaction_active>(
-        shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_WIDE_QUICK) {
-    bool success = DoIPutQuick<Primitive::kPrimLong, transaction_active>(
-        shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(IPUT_OBJECT_QUICK) {
-    bool success = DoIPutQuick<Primitive::kPrimNot, transaction_active>(
-        shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SPUT_BOOLEAN) {
-    bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SPUT_BYTE) {
-    bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimByte, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SPUT_CHAR) {
-    bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimChar, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SPUT_SHORT) {
-    bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimShort, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SPUT) {
-    bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimInt, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SPUT_WIDE) {
-    bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimLong, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SPUT_OBJECT) {
-    bool success = DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, do_access_check,
-        transaction_active>(self, shadow_frame, inst, inst_data);
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL) {
-    bool success = DoInvoke<kVirtual, false, do_access_check>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL_RANGE) {
-    bool success = DoInvoke<kVirtual, true, do_access_check>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_SUPER) {
-    bool success = DoInvoke<kSuper, false, do_access_check>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_SUPER_RANGE) {
-    bool success = DoInvoke<kSuper, true, do_access_check>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_DIRECT) {
-    bool success = DoInvoke<kDirect, false, do_access_check>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_DIRECT_RANGE) {
-    bool success = DoInvoke<kDirect, true, do_access_check>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_INTERFACE) {
-    bool success = DoInvoke<kInterface, false, do_access_check>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_INTERFACE_RANGE) {
-    bool success = DoInvoke<kInterface, true, do_access_check>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_STATIC) {
-    bool success = DoInvoke<kStatic, false, do_access_check>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_STATIC_RANGE) {
-    bool success = DoInvoke<kStatic, true, do_access_check>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL_QUICK) {
-    bool success = DoInvokeVirtualQuick<false>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INVOKE_VIRTUAL_RANGE_QUICK) {
-    bool success = DoInvokeVirtualQuick<true>(
-        self, shadow_frame, inst, inst_data, &result_register);
-    UPDATE_HANDLER_TABLE();
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 3);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(NEG_INT)
-    shadow_frame.SetVReg(
-        inst->VRegA_12x(inst_data), -shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(NOT_INT)
-    shadow_frame.SetVReg(
-        inst->VRegA_12x(inst_data), ~shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(NEG_LONG)
-    shadow_frame.SetVRegLong(
-        inst->VRegA_12x(inst_data), -shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(NOT_LONG)
-    shadow_frame.SetVRegLong(
-        inst->VRegA_12x(inst_data), ~shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(NEG_FLOAT)
-    shadow_frame.SetVRegFloat(
-        inst->VRegA_12x(inst_data), -shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(NEG_DOUBLE)
-    shadow_frame.SetVRegDouble(
-        inst->VRegA_12x(inst_data), -shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INT_TO_LONG)
-    shadow_frame.SetVRegLong(
-        inst->VRegA_12x(inst_data), shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INT_TO_FLOAT)
-    shadow_frame.SetVRegFloat(
-        inst->VRegA_12x(inst_data), shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INT_TO_DOUBLE)
-    shadow_frame.SetVRegDouble(
-        inst->VRegA_12x(inst_data), shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(LONG_TO_INT)
-    shadow_frame.SetVReg(
-        inst->VRegA_12x(inst_data), shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(LONG_TO_FLOAT)
-    shadow_frame.SetVRegFloat(
-        inst->VRegA_12x(inst_data), shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(LONG_TO_DOUBLE)
-    shadow_frame.SetVRegDouble(
-        inst->VRegA_12x(inst_data), shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(FLOAT_TO_INT) {
-    float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
-    int32_t result = art_float_to_integral<int32_t, float>(val);
-    shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(FLOAT_TO_LONG) {
-    float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
-    int64_t result = art_float_to_integral<int64_t, float>(val);
-    shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(FLOAT_TO_DOUBLE)
-    shadow_frame.SetVRegDouble(
-        inst->VRegA_12x(inst_data), shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DOUBLE_TO_INT) {
-    double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
-    int32_t result = art_float_to_integral<int32_t, double>(val);
-    shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DOUBLE_TO_LONG) {
-    double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
-    int64_t result = art_float_to_integral<int64_t, double>(val);
-    shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DOUBLE_TO_FLOAT)
-    shadow_frame.SetVRegFloat(
-        inst->VRegA_12x(inst_data), shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INT_TO_BYTE)
-    shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
-                         static_cast<int8_t>(shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INT_TO_CHAR)
-    shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
-                         static_cast<uint16_t>(shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(INT_TO_SHORT)
-    shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
-                         static_cast<int16_t>(shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ADD_INT)
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         SafeAdd(shadow_frame.GetVReg(inst->VRegB_23x()),
-                                 shadow_frame.GetVReg(inst->VRegC_23x())));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SUB_INT)
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         SafeSub(shadow_frame.GetVReg(inst->VRegB_23x()),
-                                 shadow_frame.GetVReg(inst->VRegC_23x())));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MUL_INT)
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         SafeMul(shadow_frame.GetVReg(inst->VRegB_23x()),
-                                 shadow_frame.GetVReg(inst->VRegC_23x())));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DIV_INT) {
-    bool success = DoIntDivide(shadow_frame, inst->VRegA_23x(inst_data),
-                               shadow_frame.GetVReg(inst->VRegB_23x()),
-                               shadow_frame.GetVReg(inst->VRegC_23x()));
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(REM_INT) {
-    bool success = DoIntRemainder(shadow_frame, inst->VRegA_23x(inst_data),
-                                  shadow_frame.GetVReg(inst->VRegB_23x()),
-                                  shadow_frame.GetVReg(inst->VRegC_23x()));
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SHL_INT)
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_23x()) <<
-                         (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SHR_INT)
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_23x()) >>
-                         (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(USHR_INT)
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_23x())) >>
-                         (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AND_INT)
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_23x()) &
-                         shadow_frame.GetVReg(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(OR_INT)
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_23x()) |
-                         shadow_frame.GetVReg(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(XOR_INT)
-    shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_23x()) ^
-                         shadow_frame.GetVReg(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ADD_LONG)
-    shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             SafeAdd(shadow_frame.GetVRegLong(inst->VRegB_23x()),
-                                     shadow_frame.GetVRegLong(inst->VRegC_23x())));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SUB_LONG)
-    shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             SafeSub(shadow_frame.GetVRegLong(inst->VRegB_23x()),
-                                     shadow_frame.GetVRegLong(inst->VRegC_23x())));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MUL_LONG)
-    shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             SafeMul(shadow_frame.GetVRegLong(inst->VRegB_23x()),
-                                     shadow_frame.GetVRegLong(inst->VRegC_23x())));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DIV_LONG) {
-    bool success = DoLongDivide(shadow_frame, inst->VRegA_23x(inst_data),
-                                shadow_frame.GetVRegLong(inst->VRegB_23x()),
-                                shadow_frame.GetVRegLong(inst->VRegC_23x()));
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(REM_LONG) {
-    bool success = DoLongRemainder(shadow_frame, inst->VRegA_23x(inst_data),
-                                   shadow_frame.GetVRegLong(inst->VRegB_23x()),
-                                   shadow_frame.GetVRegLong(inst->VRegC_23x()));
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AND_LONG)
-    shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVRegLong(inst->VRegB_23x()) &
-                             shadow_frame.GetVRegLong(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(OR_LONG)
-    shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVRegLong(inst->VRegB_23x()) |
-                             shadow_frame.GetVRegLong(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(XOR_LONG)
-    shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVRegLong(inst->VRegB_23x()) ^
-                             shadow_frame.GetVRegLong(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SHL_LONG)
-    shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVRegLong(inst->VRegB_23x()) <<
-                             (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SHR_LONG)
-    shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             shadow_frame.GetVRegLong(inst->VRegB_23x()) >>
-                             (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(USHR_LONG)
-    shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
-                             static_cast<uint64_t>(shadow_frame.GetVRegLong(inst->VRegB_23x())) >>
-                             (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ADD_FLOAT)
-    shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
-                              shadow_frame.GetVRegFloat(inst->VRegB_23x()) +
-                              shadow_frame.GetVRegFloat(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SUB_FLOAT)
-    shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
-                              shadow_frame.GetVRegFloat(inst->VRegB_23x()) -
-                              shadow_frame.GetVRegFloat(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MUL_FLOAT)
-    shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
-                              shadow_frame.GetVRegFloat(inst->VRegB_23x()) *
-                              shadow_frame.GetVRegFloat(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DIV_FLOAT)
-    shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
-                              shadow_frame.GetVRegFloat(inst->VRegB_23x()) /
-                              shadow_frame.GetVRegFloat(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(REM_FLOAT)
-    shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
-                              fmodf(shadow_frame.GetVRegFloat(inst->VRegB_23x()),
-                                    shadow_frame.GetVRegFloat(inst->VRegC_23x())));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ADD_DOUBLE)
-    shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
-                               shadow_frame.GetVRegDouble(inst->VRegB_23x()) +
-                               shadow_frame.GetVRegDouble(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SUB_DOUBLE)
-    shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
-                               shadow_frame.GetVRegDouble(inst->VRegB_23x()) -
-                               shadow_frame.GetVRegDouble(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MUL_DOUBLE)
-    shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
-                               shadow_frame.GetVRegDouble(inst->VRegB_23x()) *
-                               shadow_frame.GetVRegDouble(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DIV_DOUBLE)
-    shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
-                               shadow_frame.GetVRegDouble(inst->VRegB_23x()) /
-                               shadow_frame.GetVRegDouble(inst->VRegC_23x()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(REM_DOUBLE)
-    shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
-                               fmod(shadow_frame.GetVRegDouble(inst->VRegB_23x()),
-                                    shadow_frame.GetVRegDouble(inst->VRegC_23x())));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ADD_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVReg(vregA,
-                         SafeAdd(shadow_frame.GetVReg(vregA),
-                                 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SUB_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVReg(vregA,
-                         SafeSub(shadow_frame.GetVReg(vregA),
-                                 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MUL_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVReg(vregA,
-                         SafeMul(shadow_frame.GetVReg(vregA),
-                                 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DIV_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    bool success = DoIntDivide(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
-                               shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(REM_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    bool success = DoIntRemainder(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
-                                  shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SHL_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVReg(vregA,
-                         shadow_frame.GetVReg(vregA) <<
-                         (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SHR_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVReg(vregA,
-                         shadow_frame.GetVReg(vregA) >>
-                         (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(USHR_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVReg(vregA,
-                         static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
-                         (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AND_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVReg(vregA,
-                         shadow_frame.GetVReg(vregA) &
-                         shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(OR_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVReg(vregA,
-                         shadow_frame.GetVReg(vregA) |
-                         shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(XOR_INT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVReg(vregA,
-                         shadow_frame.GetVReg(vregA) ^
-                         shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ADD_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegLong(vregA,
-                             SafeAdd(shadow_frame.GetVRegLong(vregA),
-                                     shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SUB_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegLong(vregA,
-                             SafeSub(shadow_frame.GetVRegLong(vregA),
-                                     shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MUL_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegLong(vregA,
-                             SafeMul(shadow_frame.GetVRegLong(vregA),
-                                     shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DIV_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    bool success = DoLongDivide(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
-                                shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(REM_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    bool success = DoLongRemainder(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
-                                   shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AND_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegLong(vregA,
-                             shadow_frame.GetVRegLong(vregA) &
-                             shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(OR_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegLong(vregA,
-                             shadow_frame.GetVRegLong(vregA) |
-                             shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(XOR_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegLong(vregA,
-                             shadow_frame.GetVRegLong(vregA) ^
-                             shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SHL_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegLong(vregA,
-                             shadow_frame.GetVRegLong(vregA) <<
-                             (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SHR_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegLong(vregA,
-                             shadow_frame.GetVRegLong(vregA) >>
-                             (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(USHR_LONG_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegLong(vregA,
-                             static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
-                             (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ADD_FLOAT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegFloat(vregA,
-                              shadow_frame.GetVRegFloat(vregA) +
-                              shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SUB_FLOAT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegFloat(vregA,
-                              shadow_frame.GetVRegFloat(vregA) -
-                              shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MUL_FLOAT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegFloat(vregA,
-                              shadow_frame.GetVRegFloat(vregA) *
-                              shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DIV_FLOAT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegFloat(vregA,
-                              shadow_frame.GetVRegFloat(vregA) /
-                              shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(REM_FLOAT_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegFloat(vregA,
-                              fmodf(shadow_frame.GetVRegFloat(vregA),
-                                    shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ADD_DOUBLE_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegDouble(vregA,
-                               shadow_frame.GetVRegDouble(vregA) +
-                               shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SUB_DOUBLE_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegDouble(vregA,
-                               shadow_frame.GetVRegDouble(vregA) -
-                               shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MUL_DOUBLE_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegDouble(vregA,
-                               shadow_frame.GetVRegDouble(vregA) *
-                               shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DIV_DOUBLE_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegDouble(vregA,
-                               shadow_frame.GetVRegDouble(vregA) /
-                               shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(REM_DOUBLE_2ADDR) {
-    uint32_t vregA = inst->VRegA_12x(inst_data);
-    shadow_frame.SetVRegDouble(vregA,
-                               fmod(shadow_frame.GetVRegDouble(vregA),
-                                    shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data))));
-    ADVANCE(1);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ADD_INT_LIT16)
-    shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                         SafeAdd(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
-                                 inst->VRegC_22s()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(RSUB_INT)
-    shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                         SafeSub(inst->VRegC_22s(),
-                                 shadow_frame.GetVReg(inst->VRegB_22s(inst_data))));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MUL_INT_LIT16)
-    shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                         SafeMul(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
-                                 inst->VRegC_22s()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DIV_INT_LIT16) {
-    bool success = DoIntDivide(
-        shadow_frame, inst->VRegA_22s(inst_data), shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
-        inst->VRegC_22s());
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(REM_INT_LIT16) {
-    bool success = DoIntRemainder(
-        shadow_frame, inst->VRegA_22s(inst_data), shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
-        inst->VRegC_22s());
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AND_INT_LIT16)
-    shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) &
-                         inst->VRegC_22s());
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(OR_INT_LIT16)
-    shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) |
-                         inst->VRegC_22s());
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(XOR_INT_LIT16)
-    shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) ^
-                         inst->VRegC_22s());
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(ADD_INT_LIT8)
-    shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         SafeAdd(shadow_frame.GetVReg(inst->VRegB_22b()),
-                                 inst->VRegC_22b()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(RSUB_INT_LIT8)
-    shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         SafeSub(inst->VRegC_22b(),
-                                 shadow_frame.GetVReg(inst->VRegB_22b())));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(MUL_INT_LIT8)
-    shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         SafeMul(shadow_frame.GetVReg(inst->VRegB_22b()),
-                                 inst->VRegC_22b()));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(DIV_INT_LIT8) {
-    bool success = DoIntDivide(shadow_frame, inst->VRegA_22b(inst_data),
-                               shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(REM_INT_LIT8) {
-    bool success = DoIntRemainder(shadow_frame, inst->VRegA_22b(inst_data),
-                                  shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
-    POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, 2);
-  }
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(AND_INT_LIT8)
-    shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22b()) &
-                         inst->VRegC_22b());
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(OR_INT_LIT8)
-    shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22b()) |
-                         inst->VRegC_22b());
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(XOR_INT_LIT8)
-    shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22b()) ^
-                         inst->VRegC_22b());
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SHL_INT_LIT8)
-    shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22b()) <<
-                         (inst->VRegC_22b() & 0x1f));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(SHR_INT_LIT8)
-    shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         shadow_frame.GetVReg(inst->VRegB_22b()) >>
-                         (inst->VRegC_22b() & 0x1f));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(USHR_INT_LIT8)
-    shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
-                         static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_22b())) >>
-                         (inst->VRegC_22b() & 0x1f));
-    ADVANCE(2);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_3E)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_3F)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_40)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_41)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_42)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_43)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_79)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_7A)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_F3)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_F4)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_F5)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_F6)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_F7)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_F8)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_F9)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_FA)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_FB)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_FC)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_FD)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_FE)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  HANDLE_INSTRUCTION_START(UNUSED_FF)
-    UnexpectedOpcode(inst, shadow_frame);
-  HANDLE_INSTRUCTION_END();
-
-  exception_pending_label: {
-    CHECK(self->IsExceptionPending());
-    if (UNLIKELY(self->TestAllFlags())) {
-      self->CheckSuspend();
-      UPDATE_HANDLER_TABLE();
-    }
-    uint32_t found_dex_pc = FindNextInstructionFollowingException(self, shadow_frame, dex_pc,
-                                                                  instrumentation);
-    if (found_dex_pc == DexFile::kDexNoIndex) {
-      // Structured locking is to be enforced for abnormal termination, too.
-      DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
-      return JValue(); /* Handled in caller. */
-    } else {
-      int32_t displacement = static_cast<int32_t>(found_dex_pc) - static_cast<int32_t>(dex_pc);
-      ADVANCE(displacement);
-    }
-  }
-
-// Create alternative instruction handlers dedicated to instrumentation.
-// Return instructions must not call Instrumentation::DexPcMovedEvent since they already call
-// Instrumentation::MethodExited. This is to avoid posting debugger events twice for this location.
-// Note: we do not use the kReturn instruction flag here (to test the instruction is a return). The
-// compiler seems to not evaluate "(Instruction::FlagsOf(Instruction::code) & kReturn) != 0" to
-// a constant condition that would remove the "if" statement so the test is free.
-#define INSTRUMENTATION_INSTRUCTION_HANDLER(o, code, n, f, i, a, v)                        \
-  alt_op_##code: {                                                                            \
-    if (UNLIKELY(instrumentation->HasDexPcListeners())) {                                     \
-      Object* this_object = shadow_frame.GetThisObject(code_item->ins_size_);                 \
-      instrumentation->DexPcMovedEvent(self, this_object, shadow_frame.GetMethod(), dex_pc);  \
-    }                                                                                         \
-    UPDATE_HANDLER_TABLE();                                                                   \
-    goto *handlersTable[instrumentation::kMainHandlerTable][Instruction::code];               \
-  }
-#include "dex_instruction_list.h"
-      DEX_INSTRUCTION_LIST(INSTRUMENTATION_INSTRUCTION_HANDLER)
-#undef DEX_INSTRUCTION_LIST
-#undef INSTRUMENTATION_INSTRUCTION_HANDLER
-}  // NOLINT(readability/fn_size)
-
-// Explicit definitions of ExecuteGotoImpl.
-template HOT_ATTR
-JValue ExecuteGotoImpl<true, false>(Thread* self, const DexFile::CodeItem* code_item,
-                                    ShadowFrame& shadow_frame, JValue result_register);
-template HOT_ATTR
-JValue ExecuteGotoImpl<false, false>(Thread* self, const DexFile::CodeItem* code_item,
-                                     ShadowFrame& shadow_frame, JValue result_register);
-template
-JValue ExecuteGotoImpl<true, true>(Thread* self, const DexFile::CodeItem* code_item,
-                                   ShadowFrame& shadow_frame, JValue result_register);
-template
-JValue ExecuteGotoImpl<false, true>(Thread* self, const DexFile::CodeItem* code_item,
-                                    ShadowFrame& shadow_frame, JValue result_register);
-
-#else
-
-template<bool do_access_check, bool transaction_active>
-JValue ExecuteGotoImpl(Thread*, const DexFile::CodeItem*, ShadowFrame&, JValue) {
-  LOG(FATAL) << "UNREACHABLE";
-  UNREACHABLE();
-}
-// Explicit definitions of ExecuteGotoImpl.
-template<>
-JValue ExecuteGotoImpl<true, false>(Thread* self, const DexFile::CodeItem* code_item,
-                                    ShadowFrame& shadow_frame, JValue result_register);
-template<>
-JValue ExecuteGotoImpl<false, false>(Thread* self, const DexFile::CodeItem* code_item,
-                                     ShadowFrame& shadow_frame, JValue result_register);
-template<>
-JValue ExecuteGotoImpl<true, true>(Thread* self,  const DexFile::CodeItem* code_item,
-                                   ShadowFrame& shadow_frame, JValue result_register);
-template<>
-JValue ExecuteGotoImpl<false, true>(Thread* self, const DexFile::CodeItem* code_item,
-                                    ShadowFrame& shadow_frame, JValue result_register);
-#endif
-
-}  // namespace interpreter
-}  // namespace art
diff --git a/runtime/interpreter/interpreter_goto_table_impl.h b/runtime/interpreter/interpreter_goto_table_impl.h
deleted file mode 100644
index c54746d..0000000
--- a/runtime/interpreter/interpreter_goto_table_impl.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2012 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_INTERPRETER_INTERPRETER_GOTO_TABLE_IMPL_H_
-#define ART_RUNTIME_INTERPRETER_INTERPRETER_GOTO_TABLE_IMPL_H_
-
-#include "base/macros.h"
-#include "base/mutex.h"
-#include "dex_file.h"
-#include "jvalue.h"
-
-namespace art {
-
-class ShadowFrame;
-class Thread;
-
-namespace interpreter {
-
-template<bool do_access_check, bool transaction_active>
-JValue ExecuteGotoImpl(Thread* self,
-                       const DexFile::CodeItem* code_item,
-                       ShadowFrame& shadow_frame,
-                       JValue result_register) REQUIRES_SHARED(Locks::mutator_lock_);
-
-}  // namespace interpreter
-}  // namespace art
-
-#endif  // ART_RUNTIME_INTERPRETER_INTERPRETER_GOTO_TABLE_IMPL_H_
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index a3071b7..220979a 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -44,13 +44,29 @@
 
 inline void DexCache::SetResolvedString(uint32_t string_idx, mirror::String* resolved) {
   DCHECK_LT(string_idx % NumStrings(), NumStrings());
-  // TODO default transaction support.
-  StringDexCachePair idx_ptr;
-  idx_ptr.string_index = string_idx;
-  idx_ptr.string_pointer = GcRoot<String>(resolved);
-  GetStrings()[string_idx % NumStrings()].store(idx_ptr, std::memory_order_relaxed);
+  GetStrings()[string_idx % NumStrings()].store(
+      StringDexCachePair(resolved, string_idx),
+      std::memory_order_relaxed);
+  Runtime* const runtime = Runtime::Current();
+  if (UNLIKELY(runtime->IsActiveTransaction())) {
+    DCHECK(runtime->IsAotCompiler());
+    runtime->RecordResolveString(this, string_idx);
+  }
   // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
-  Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this);
+  runtime->GetHeap()->WriteBarrierEveryFieldOf(this);
+}
+
+inline void DexCache::ClearString(uint32_t string_idx) {
+  const uint32_t slot_idx = string_idx % NumStrings();
+  DCHECK(Runtime::Current()->IsAotCompiler());
+  StringDexCacheType* slot = &GetStrings()[slot_idx];
+  // This is racy but should only be called from the transactional interpreter.
+  if (slot->load(std::memory_order_relaxed).string_index == string_idx) {
+    StringDexCachePair cleared(
+        nullptr,
+        StringDexCachePair::InvalidStringIndexForSlot(slot_idx));
+    slot->store(cleared, std::memory_order_relaxed);
+  }
 }
 
 inline Class* DexCache::GetResolvedType(uint32_t type_idx) {
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index caf00c2..7d4021f 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -56,12 +56,20 @@
   // it's always non-null if the string id branch succeeds (except for the 0th string id).
   // Set the initial state for the 0th entry to be {0,1} which is guaranteed to fail
   // the lookup string id == stored id branch.
+  StringDexCachePair(String* string, uint32_t string_idx)
+      : string_pointer(string),
+        string_index(string_idx) {}
+  StringDexCachePair() = default;
+  StringDexCachePair(const StringDexCachePair&) = default;
+  StringDexCachePair& operator=(const StringDexCachePair&) = default;
+
   static void Initialize(StringDexCacheType* strings) {
     mirror::StringDexCachePair first_elem;
     first_elem.string_pointer = GcRoot<String>(nullptr);
-    first_elem.string_index = 1;
+    first_elem.string_index = InvalidStringIndexForSlot(0);
     strings[0].store(first_elem, std::memory_order_relaxed);
   }
+
   static GcRoot<String> LookupString(StringDexCacheType* dex_cache,
                                      uint32_t string_idx,
                                      uint32_t cache_size) {
@@ -71,10 +79,15 @@
     DCHECK(!index_string.string_pointer.IsNull());
     return index_string.string_pointer;
   }
+
+  static uint32_t InvalidStringIndexForSlot(uint32_t slot) {
+    // Since the cache size is a power of two, 0 will always map to slot 0.
+    // Use 1 for slot 0 and 0 for all other slots.
+    return (slot == 0) ? 1u : 0u;
+  }
 };
 using StringDexCacheType = std::atomic<StringDexCachePair>;
 
-
 // C++ mirror of java.lang.DexCache.
 class MANAGED DexCache FINAL : public Object {
  public:
@@ -164,6 +177,10 @@
   void SetResolvedString(uint32_t string_idx, mirror::String* resolved) ALWAYS_INLINE
       REQUIRES_SHARED(Locks::mutator_lock_);
 
+  // Clear a string for a string_idx, used to undo string intern transactions to make sure
+  // the string isn't kept live.
+  void ClearString(uint32_t string_idx) REQUIRES_SHARED(Locks::mutator_lock_);
+
   Class* GetResolvedType(uint32_t type_idx) REQUIRES_SHARED(Locks::mutator_lock_);
 
   void SetResolvedType(uint32_t type_idx, Class* resolved) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index a365a73..ba12d33 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1929,6 +1929,12 @@
   preinitialization_transaction_->RecordWeakStringRemoval(s);
 }
 
+void Runtime::RecordResolveString(mirror::DexCache* dex_cache, uint32_t string_idx) const {
+  DCHECK(IsAotCompiler());
+  DCHECK(IsActiveTransaction());
+  preinitialization_transaction_->RecordResolveString(dex_cache, string_idx);
+}
+
 void Runtime::SetFaultMessage(const std::string& message) {
   MutexLock mu(Thread::Current(), fault_message_lock_);
   fault_message_ = message;
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 44f765a..dc14c04 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -55,8 +55,9 @@
 }  // namespace jit
 
 namespace mirror {
-  class ClassLoader;
   class Array;
+  class ClassLoader;
+  class DexCache;
   template<class T> class ObjectArray;
   template<class T> class PrimitiveArray;
   typedef PrimitiveArray<int8_t> ByteArray;
@@ -508,6 +509,8 @@
       REQUIRES(Locks::intern_table_lock_);
   void RecordWeakStringRemoval(mirror::String* s) const
       REQUIRES(Locks::intern_table_lock_);
+  void RecordResolveString(mirror::DexCache* dex_cache, uint32_t string_idx) const
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
   void SetFaultMessage(const std::string& message) REQUIRES(!fault_message_lock_);
   // Only read by the signal handler, NO_THREAD_SAFETY_ANALYSIS to prevent lock order violations
diff --git a/runtime/simulator/Android.bp b/runtime/simulator/Android.bp
index ec0b49e..49322fc 100644
--- a/runtime/simulator/Android.bp
+++ b/runtime/simulator/Android.bp
@@ -16,6 +16,9 @@
 
 cc_defaults {
     name: "libart_simulator_defaults",
+    host_supported: true,
+    device_supported: false,
+
     defaults: ["art_defaults"],
     srcs: [
         "code_simulator.cc",
@@ -29,7 +32,7 @@
     include_dirs: ["art/runtime"],
 }
 
-cc_library_host_shared {
+art_cc_library {
     name: "libart-simulator",
     defaults: ["libart_simulator_defaults"],
     shared_libs: [
@@ -38,7 +41,7 @@
     ],
 }
 
-cc_library_host_shared {
+art_cc_library {
     name: "libartd-simulator",
     defaults: [
         "art_debug_defaults",
diff --git a/runtime/simulator/code_simulator_arm64.cc b/runtime/simulator/code_simulator_arm64.cc
index 897d4f5..c7ad1fd 100644
--- a/runtime/simulator/code_simulator_arm64.cc
+++ b/runtime/simulator/code_simulator_arm64.cc
@@ -16,6 +16,8 @@
 
 #include "simulator/code_simulator_arm64.h"
 
+#include "base/logging.h"
+
 using namespace vixl::aarch64;  // NOLINT(build/namespaces)
 
 namespace art {
diff --git a/runtime/transaction.cc b/runtime/transaction.cc
index d91860b..9f8d981 100644
--- a/runtime/transaction.cc
+++ b/runtime/transaction.cc
@@ -49,13 +49,15 @@
     for (auto it : array_logs_) {
       array_values_count += it.second.Size();
     }
-    size_t string_count = intern_string_logs_.size();
+    size_t intern_string_count = intern_string_logs_.size();
+    size_t resolve_string_count = resolve_string_logs_.size();
     LOG(INFO) << "Transaction::~Transaction"
               << ": objects_count=" << objects_count
               << ", field_values_count=" << field_values_count
               << ", array_count=" << array_count
               << ", array_values_count=" << array_values_count
-              << ", string_count=" << string_count;
+              << ", intern_string_count=" << intern_string_count
+              << ", resolve_string_count=" << resolve_string_count;
   }
 }
 
@@ -165,6 +167,13 @@
   array_log.LogValue(index, value);
 }
 
+void Transaction::RecordResolveString(mirror::DexCache* dex_cache, uint32_t string_idx) {
+  DCHECK(dex_cache != nullptr);
+  DCHECK_LT(string_idx, dex_cache->GetDexFile()->NumStringIds());
+  MutexLock mu(Thread::Current(), log_lock_);
+  resolve_string_logs_.push_back(ResolveStringLog(dex_cache, string_idx));
+}
+
 void Transaction::RecordStrongStringInsertion(mirror::String* s) {
   InternStringLog log(s, InternStringLog::kStrongString, InternStringLog::kInsert);
   LogInternedString(log);
@@ -200,6 +209,7 @@
   UndoObjectModifications();
   UndoArrayModifications();
   UndoInternStringTableModifications();
+  UndoResolveStringModifications();
 }
 
 void Transaction::UndoObjectModifications() {
@@ -230,11 +240,19 @@
   intern_string_logs_.clear();
 }
 
+void Transaction::UndoResolveStringModifications() {
+  for (ResolveStringLog& string_log : resolve_string_logs_) {
+    string_log.Undo();
+  }
+  resolve_string_logs_.clear();
+}
+
 void Transaction::VisitRoots(RootVisitor* visitor) {
   MutexLock mu(Thread::Current(), log_lock_);
   VisitObjectLogs(visitor);
   VisitArrayLogs(visitor);
-  VisitStringLogs(visitor);
+  VisitInternStringLogs(visitor);
+  VisitResolveStringLogs(visitor);
 }
 
 void Transaction::VisitObjectLogs(RootVisitor* visitor) {
@@ -292,12 +310,18 @@
   }
 }
 
-void Transaction::VisitStringLogs(RootVisitor* visitor) {
+void Transaction::VisitInternStringLogs(RootVisitor* visitor) {
   for (InternStringLog& log : intern_string_logs_) {
     log.VisitRoots(visitor);
   }
 }
 
+void Transaction::VisitResolveStringLogs(RootVisitor* visitor) {
+  for (ResolveStringLog& log : resolve_string_logs_) {
+    log.VisitRoots(visitor);
+  }
+}
+
 void Transaction::ObjectLog::LogBooleanValue(MemberOffset offset, uint8_t value, bool is_volatile) {
   LogValue(ObjectLog::kBoolean, offset, value, is_volatile);
 }
@@ -481,6 +505,21 @@
   visitor->VisitRoot(reinterpret_cast<mirror::Object**>(&str_), RootInfo(kRootInternedString));
 }
 
+void Transaction::ResolveStringLog::Undo() {
+  dex_cache_.Read()->ClearString(string_idx_);
+}
+
+Transaction::ResolveStringLog::ResolveStringLog(mirror::DexCache* dex_cache, uint32_t string_idx)
+    : dex_cache_(dex_cache),
+      string_idx_(string_idx) {
+  DCHECK(dex_cache != nullptr);
+  DCHECK_LT(string_idx_, dex_cache->GetDexFile()->NumStringIds());
+}
+
+void Transaction::ResolveStringLog::VisitRoots(RootVisitor* visitor) {
+  dex_cache_.VisitRoot(visitor, RootInfo(kRootVMInternal));
+}
+
 void Transaction::ArrayLog::LogValue(size_t index, uint64_t value) {
   auto it = array_values_.find(index);
   if (it == array_values_.end()) {
diff --git a/runtime/transaction.h b/runtime/transaction.h
index bc9c640..584dfb89 100644
--- a/runtime/transaction.h
+++ b/runtime/transaction.h
@@ -32,6 +32,7 @@
 namespace art {
 namespace mirror {
 class Array;
+class DexCache;
 class Object;
 class String;
 }
@@ -95,6 +96,11 @@
       REQUIRES(Locks::intern_table_lock_)
       REQUIRES(!log_lock_);
 
+  // Record resolve string.
+  void RecordResolveString(mirror::DexCache* dex_cache, uint32_t string_idx)
+      REQUIRES_SHARED(Locks::mutator_lock_)
+      REQUIRES(!log_lock_);
+
   // Abort transaction by undoing all recorded changes.
   void Rollback()
       REQUIRES_SHARED(Locks::mutator_lock_)
@@ -192,6 +198,19 @@
     const StringOp string_op_;
   };
 
+  class ResolveStringLog : public ValueObject {
+   public:
+    ResolveStringLog(mirror::DexCache* dex_cache, uint32_t string_idx);
+
+    void Undo() REQUIRES_SHARED(Locks::mutator_lock_);
+
+    void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
+
+   private:
+    GcRoot<mirror::DexCache> dex_cache_;
+    const uint32_t string_idx_;
+  };
+
   void LogInternedString(const InternStringLog& log)
       REQUIRES(Locks::intern_table_lock_)
       REQUIRES(!log_lock_);
@@ -206,6 +225,9 @@
       REQUIRES(Locks::intern_table_lock_)
       REQUIRES(log_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
+  void UndoResolveStringModifications()
+      REQUIRES(log_lock_)
+      REQUIRES_SHARED(Locks::mutator_lock_);
 
   void VisitObjectLogs(RootVisitor* visitor)
       REQUIRES(log_lock_)
@@ -213,7 +235,10 @@
   void VisitArrayLogs(RootVisitor* visitor)
       REQUIRES(log_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
-  void VisitStringLogs(RootVisitor* visitor)
+  void VisitInternStringLogs(RootVisitor* visitor)
+      REQUIRES(log_lock_)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  void VisitResolveStringLogs(RootVisitor* visitor)
       REQUIRES(log_lock_)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
@@ -223,6 +248,7 @@
   std::map<mirror::Object*, ObjectLog> object_logs_ GUARDED_BY(log_lock_);
   std::map<mirror::Array*, ArrayLog> array_logs_  GUARDED_BY(log_lock_);
   std::list<InternStringLog> intern_string_logs_ GUARDED_BY(log_lock_);
+  std::list<ResolveStringLog> resolve_string_logs_ GUARDED_BY(log_lock_);
   bool aborted_ GUARDED_BY(log_lock_);
   std::string abort_message_ GUARDED_BY(log_lock_);
 
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 8279a26..82e529c 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -20,11 +20,14 @@
 #include "art_method-inl.h"
 #include "class_linker-inl.h"
 #include "common_runtime_test.h"
+#include "dex_file.h"
 #include "mirror/array-inl.h"
 #include "scoped_thread_state_change.h"
 
 namespace art {
 
+static const size_t kDexNoIndex = DexFile::kDexNoIndex;  // Make copy to prevent linking errors.
+
 class TransactionTest : public CommonRuntimeTest {
  public:
   // Tests failing class initialization due to native call with transaction rollback.
@@ -482,6 +485,55 @@
   EXPECT_EQ(objectArray->GetWithoutChecks(0), nullptr);
 }
 
+// Tests rolling back interned strings and resolved strings.
+TEST_F(TransactionTest, ResolveString) {
+  ScopedObjectAccess soa(Thread::Current());
+  StackHandleScope<3> hs(soa.Self());
+  Handle<mirror::ClassLoader> class_loader(
+      hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
+  ASSERT_TRUE(class_loader.Get() != nullptr);
+
+  Handle<mirror::Class> h_klass(
+      hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$ResolveString;",
+                                            class_loader)));
+  ASSERT_TRUE(h_klass.Get() != nullptr);
+
+  Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(h_klass->GetDexCache()));
+  ASSERT_TRUE(h_dex_cache.Get() != nullptr);
+  const DexFile* const dex_file = h_dex_cache->GetDexFile();
+  ASSERT_TRUE(dex_file != nullptr);
+
+  // Go search the dex file to find the string id of our string.
+  static const char* kResolvedString = "ResolvedString";
+  const DexFile::StringId* string_id = dex_file->FindStringId(kResolvedString);
+  ASSERT_TRUE(string_id != nullptr);
+  uint32_t string_idx = dex_file->GetIndexForStringId(*string_id);
+  ASSERT_NE(string_idx, kDexNoIndex);
+  // String should only get resolved by the initializer.
+  EXPECT_TRUE(class_linker_->LookupString(*dex_file, string_idx, h_dex_cache) == nullptr);
+  EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
+  // Do the transaction, then roll back.
+  Transaction transaction;
+  Runtime::Current()->EnterTransactionMode(&transaction);
+  bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
+  ASSERT_TRUE(success);
+  ASSERT_TRUE(h_klass->IsInitialized());
+  // Make sure the string got resolved by the transaction.
+  {
+    mirror::String* s = class_linker_->LookupString(*dex_file, string_idx, h_dex_cache);
+    ASSERT_TRUE(s != nullptr);
+    EXPECT_STREQ(s->ToModifiedUtf8().c_str(), kResolvedString);
+    EXPECT_EQ(s, h_dex_cache->GetResolvedString(string_idx));
+  }
+  Runtime::Current()->ExitTransactionMode();
+  transaction.Rollback();
+  // Check that the string did not stay resolved.
+  EXPECT_TRUE(class_linker_->LookupString(*dex_file, string_idx, h_dex_cache) == nullptr);
+  EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
+  ASSERT_FALSE(h_klass->IsInitialized());
+  ASSERT_FALSE(soa.Self()->IsExceptionPending());
+}
+
 // Tests successful class initialization without class initializer.
 TEST_F(TransactionTest, EmptyClass) {
   ScopedObjectAccess soa(Thread::Current());
diff --git a/runtime/utils.h b/runtime/utils.h
index 2389ce7..958f0a3 100644
--- a/runtime/utils.h
+++ b/runtime/utils.h
@@ -386,6 +386,16 @@
   __builtin___clear_cache(begin, end);
 }
 
+template <typename T>
+constexpr PointerSize ConvertToPointerSize(T any) {
+  if (any == 4 || any == 8) {
+    return static_cast<PointerSize>(any);
+  } else {
+    LOG(FATAL);
+    UNREACHABLE();
+  }
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_UTILS_H_
diff --git a/runtime/utils/dex_cache_arrays_layout-inl.h b/runtime/utils/dex_cache_arrays_layout-inl.h
index 4c63156..a85d033 100644
--- a/runtime/utils/dex_cache_arrays_layout-inl.h
+++ b/runtime/utils/dex_cache_arrays_layout-inl.h
@@ -55,7 +55,8 @@
 
 template <typename T>
 static constexpr PointerSize GcRootAsPointerSize() {
-  return ConvertToPointerSize(sizeof(GcRoot<T>));
+  static_assert(sizeof(GcRoot<T>) == 4U, "Unexpected GcRoot size");
+  return PointerSize::k32;
 }
 
 inline size_t DexCacheArraysLayout::TypeOffset(uint32_t type_idx) const {
diff --git a/test/538-checker-embed-constants/src/Main.java b/test/538-checker-embed-constants/src/Main.java
index f6713a2..04a12fa 100644
--- a/test/538-checker-embed-constants/src/Main.java
+++ b/test/538-checker-embed-constants/src/Main.java
@@ -102,12 +102,12 @@
 
   /// CHECK-START-ARM: long Main.and255(long) disassembly (after)
   /// CHECK-NOT:            movs {{r\d+}}, #255
-  /// CHECK-NOT:            and
-  /// CHECK-NOT:            bic
+  /// CHECK-NOT:            and{{(\.w)?}}
+  /// CHECK-NOT:            bic{{(\.w)?}}
   /// CHECK-DAG:            and {{r\d+}}, {{r\d+}}, #255
   /// CHECK-DAG:            movs {{r\d+}}, #0
-  /// CHECK-NOT:            and
-  /// CHECK-NOT:            bic
+  /// CHECK-NOT:            and{{(\.w)?}}
+  /// CHECK-NOT:            bic{{(\.w)?}}
 
   public static long and255(long arg) {
     return arg & 255L;
@@ -115,12 +115,13 @@
 
   /// CHECK-START-ARM: long Main.and511(long) disassembly (after)
   /// CHECK:                movw {{r\d+}}, #511
-  /// CHECK-NOT:            and
-  /// CHECK-NOT:            bic
-  /// CHECK-DAG:            and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
-  /// CHECK-DAG:            movs {{r\d+}}, #0
-  /// CHECK-NOT:            and
-  /// CHECK-NOT:            bic
+  /// CHECK-NEXT:           movs {{r\d+}}, #0
+  /// CHECK-NOT:            and{{(\.w)?}}
+  /// CHECK-NOT:            bic{{(\.w)?}}
+  /// CHECK:                and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+  /// CHECK-NEXT:           and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+  /// CHECK-NOT:            and{{(\.w)?}}
+  /// CHECK-NOT:            bic{{(\.w)?}}
 
   public static long and511(long arg) {
     return arg & 511L;
@@ -128,11 +129,11 @@
 
   /// CHECK-START-ARM: long Main.andNot15(long) disassembly (after)
   /// CHECK-NOT:            mvn {{r\d+}}, #15
-  /// CHECK-NOT:            and
-  /// CHECK-NOT:            bic
+  /// CHECK-NOT:            and{{(\.w)?}}
+  /// CHECK-NOT:            bic{{(\.w)?}}
   /// CHECK:                bic {{r\d+}}, {{r\d+}}, #15
-  /// CHECK-NOT:            and
-  /// CHECK-NOT:            bic
+  /// CHECK-NOT:            and{{(\.w)?}}
+  /// CHECK-NOT:            bic{{(\.w)?}}
 
   public static long andNot15(long arg) {
     return arg & ~15L;
@@ -141,12 +142,12 @@
   /// CHECK-START-ARM: long Main.and0xfffffff00000000f(long) disassembly (after)
   /// CHECK-NOT:            movs {{r\d+}}, #15
   /// CHECK-NOT:            mvn {{r\d+}}, #15
-  /// CHECK-NOT:            and
-  /// CHECK-NOT:            bic
+  /// CHECK-NOT:            and{{(\.w)?}}
+  /// CHECK-NOT:            bic{{(\.w)?}}
   /// CHECK-DAG:            and {{r\d+}}, {{r\d+}}, #15
   /// CHECK-DAG:            bic {{r\d+}}, {{r\d+}}, #15
-  /// CHECK-NOT:            and
-  /// CHECK-NOT:            bic
+  /// CHECK-NOT:            and{{(\.w)?}}
+  /// CHECK-NOT:            bic{{(\.w)?}}
 
   public static long and0xfffffff00000000f(long arg) {
     return arg & 0xfffffff00000000fL;
@@ -154,10 +155,10 @@
 
   /// CHECK-START-ARM: long Main.or255(long) disassembly (after)
   /// CHECK-NOT:            movs {{r\d+}}, #255
-  /// CHECK-NOT:            orr
+  /// CHECK-NOT:            orr{{(\.w)?}}
   /// CHECK-NOT:            orn
   /// CHECK:                orr {{r\d+}}, {{r\d+}}, #255
-  /// CHECK-NOT:            orr
+  /// CHECK-NOT:            orr{{(\.w)?}}
   /// CHECK-NOT:            orn
 
   public static long or255(long arg) {
@@ -166,10 +167,12 @@
 
   /// CHECK-START-ARM: long Main.or511(long) disassembly (after)
   /// CHECK:                movw {{r\d+}}, #511
-  /// CHECK-NOT:            orr
+  /// CHECK-NEXT:           movs {{r\d+}}, #0
+  /// CHECK-NOT:            orr{{(\.w)?}}
   /// CHECK-NOT:            orn
   /// CHECK:                orr{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
-  /// CHECK-NOT:            orr
+  /// CHECK-NEXT:           orr{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+  /// CHECK-NOT:            orr{{(\.w)?}}
   /// CHECK-NOT:            orn
 
   public static long or511(long arg) {
@@ -178,11 +181,11 @@
 
   /// CHECK-START-ARM: long Main.orNot15(long) disassembly (after)
   /// CHECK-NOT:            mvn {{r\d+}}, #15
-  /// CHECK-NOT:            orr
+  /// CHECK-NOT:            orr{{(\.w)?}}
   /// CHECK-NOT:            orn
   /// CHECK-DAG:            orn {{r\d+}}, {{r\d+}}, #15
   /// CHECK-DAG:            mvn {{r\d+}}, #0
-  /// CHECK-NOT:            orr
+  /// CHECK-NOT:            orr{{(\.w)?}}
   /// CHECK-NOT:            orn
 
   public static long orNot15(long arg) {
@@ -192,11 +195,11 @@
   /// CHECK-START-ARM: long Main.or0xfffffff00000000f(long) disassembly (after)
   /// CHECK-NOT:            movs {{r\d+}}, #15
   /// CHECK-NOT:            mvn {{r\d+}}, #15
-  /// CHECK-NOT:            orr
+  /// CHECK-NOT:            orr{{(\.w)?}}
   /// CHECK-NOT:            orn
   /// CHECK-DAG:            orr {{r\d+}}, {{r\d+}}, #15
   /// CHECK-DAG:            orn {{r\d+}}, {{r\d+}}, #15
-  /// CHECK-NOT:            orr
+  /// CHECK-NOT:            orr{{(\.w)?}}
   /// CHECK-NOT:            orn
 
   public static long or0xfffffff00000000f(long arg) {
@@ -205,9 +208,9 @@
 
   /// CHECK-START-ARM: long Main.xor255(long) disassembly (after)
   /// CHECK-NOT:            movs {{r\d+}}, #255
-  /// CHECK-NOT:            eor
+  /// CHECK-NOT:            eor{{(\.w)?}}
   /// CHECK:                eor {{r\d+}}, {{r\d+}}, #255
-  /// CHECK-NOT:            eor
+  /// CHECK-NOT:            eor{{(\.w)?}}
 
   public static long xor255(long arg) {
     return arg ^ 255L;
@@ -215,9 +218,11 @@
 
   /// CHECK-START-ARM: long Main.xor511(long) disassembly (after)
   /// CHECK:                movw {{r\d+}}, #511
-  /// CHECK-NOT:            eor
-  /// CHECK-DAG:            eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
-  /// CHECK-NOT:            eor
+  /// CHECK-NEXT:           movs {{r\d+}}, #0
+  /// CHECK-NOT:            eor{{(\.w)?}}
+  /// CHECK:                eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+  /// CHECK-NEXT:           eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+  /// CHECK-NOT:            eor{{(\.w)?}}
 
   public static long xor511(long arg) {
     return arg ^ 511L;
@@ -226,10 +231,10 @@
   /// CHECK-START-ARM: long Main.xorNot15(long) disassembly (after)
   /// CHECK-DAG:            mvn {{r\d+}}, #15
   /// CHECK-DAG:            mov.w {{r\d+}}, #-1
-  /// CHECK-NOT:            eor
+  /// CHECK-NOT:            eor{{(\.w)?}}
   /// CHECK-DAG:            eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
   /// CHECK-DAG:            eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
-  /// CHECK-NOT:            eor
+  /// CHECK-NOT:            eor{{(\.w)?}}
 
   public static long xorNot15(long arg) {
     return arg ^ ~15L;
@@ -239,10 +244,10 @@
   /// CHECK-START-ARM: long Main.xor0xfffffff00000000f(long) disassembly (after)
   /// CHECK-DAG:            movs {{r\d+}}, #15
   /// CHECK-DAG:            mvn {{r\d+}}, #15
-  /// CHECK-NOT:            eor
+  /// CHECK-NOT:            eor{{(\.w)?}}
   /// CHECK-DAG:            eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
   /// CHECK-DAG:            eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
-  /// CHECK-NOT:            eor
+  /// CHECK-NOT:            eor{{(\.w)?}}
 
   public static long xor0xfffffff00000000f(long arg) {
     return arg ^ 0xfffffff00000000fL;
@@ -251,10 +256,10 @@
   /// CHECK-START-ARM: long Main.xor0xf00000000000000f(long) disassembly (after)
   /// CHECK-NOT:            movs {{r\d+}}, #15
   /// CHECK-NOT:            mov.w {{r\d+}}, #-268435456
-  /// CHECK-NOT:            eor
+  /// CHECK-NOT:            eor{{(\.w)?}}
   /// CHECK-DAG:            eor {{r\d+}}, {{r\d+}}, #15
   /// CHECK-DAG:            eor {{r\d+}}, {{r\d+}}, #-268435456
-  /// CHECK-NOT:            eor
+  /// CHECK-NOT:            eor{{(\.w)?}}
 
   public static long xor0xf00000000000000f(long arg) {
     return arg ^ 0xf00000000000000fL;
diff --git a/test/Transaction/Transaction.java b/test/Transaction/Transaction.java
index 00e1fbb..e7085c1 100644
--- a/test/Transaction/Transaction.java
+++ b/test/Transaction/Transaction.java
@@ -18,6 +18,10 @@
     static class EmptyStatic {
     }
 
+    static class ResolveString {
+      static String s = "ResolvedString";
+    }
+
     static class StaticFieldClass {
       public static int intField;
       static {
diff --git a/tools/bisection-search/README.md b/tools/bisection_search/README.md
similarity index 100%
rename from tools/bisection-search/README.md
rename to tools/bisection_search/README.md
diff --git a/tools/bisection_search/__init__.py b/tools/bisection_search/__init__.py
new file mode 100644
index 0000000..0a42789
--- /dev/null
+++ b/tools/bisection_search/__init__.py
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2016 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.
+#
+
+# This file is intentionally left empty. It indicates that the directory is a Python package.
diff --git a/tools/bisection-search/bisection_search.py b/tools/bisection_search/bisection_search.py
similarity index 100%
rename from tools/bisection-search/bisection_search.py
rename to tools/bisection_search/bisection_search.py
diff --git a/tools/bisection-search/bisection_test.py b/tools/bisection_search/bisection_test.py
similarity index 100%
rename from tools/bisection-search/bisection_test.py
rename to tools/bisection_search/bisection_test.py
diff --git a/tools/bisection-search/common.py b/tools/bisection_search/common.py
similarity index 100%
rename from tools/bisection-search/common.py
rename to tools/bisection_search/common.py
diff --git a/tools/cpp-define-generator/Android.bp b/tools/cpp-define-generator/Android.bp
new file mode 100644
index 0000000..d792e90
--- /dev/null
+++ b/tools/cpp-define-generator/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2014 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.
+//
+
+// Build a "data" binary which will hold all the symbol values that will be parsed by the other scripts.
+//
+// Builds are for host only, target-specific define generation is possibly but is trickier and would need extra tooling.
+//
+// In the future we may wish to parameterize this on (32,64)x(read_barrier,no_read_barrier).
+
+art_cc_binary {
+    name: "cpp-define-generator-data",
+    host_supported: true,
+    device_supported: false,
+    defaults: [
+        "art_debug_defaults",
+        "art_defaults",
+    ],
+    include_dirs: ["art/runtime"],
+    srcs: ["main.cc"],
+    shared_libs: [
+        "libbase",
+    ],
+}
diff --git a/tools/cpp-define-generator/Android.mk b/tools/cpp-define-generator/Android.mk
deleted file mode 100644
index 6ba643c..0000000
--- a/tools/cpp-define-generator/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include art/build/Android.executable.mk
-
-CPP_DEFINE_GENERATOR_SRC_FILES := \
-  main.cc
-
-CPP_DEFINE_GENERATOR_EXTRA_SHARED_LIBRARIES :=
-CPP_DEFINE_GENERATOR_EXTRA_INCLUDE :=
-CPP_DEFINE_GENERATOR_MULTILIB :=
-
-# Build a "data" binary which will hold all the symbol values that will be parsed by the other scripts.
-#
-# Builds are for host only, target-specific define generation is possibly but is trickier and would need extra tooling.
-#
-# In the future we may wish to parameterize this on (32,64)x(read_barrier,no_read_barrier).
-$(eval $(call build-art-executable,cpp-define-generator-data,$(CPP_DEFINE_GENERATOR_SRC_FILES),$(CPP_DEFINE_GENERATOR_EXTRA_SHARED_LIBRARIES),$(CPP_DEFINE_GENERATOR_EXTRA_INCLUDE),host,debug,$(CPP_DEFINE_GENERATOR_MULTILIB),shared))
-
diff --git a/tools/dmtracedump/Android.bp b/tools/dmtracedump/Android.bp
new file mode 100644
index 0000000..4f942bd
--- /dev/null
+++ b/tools/dmtracedump/Android.bp
@@ -0,0 +1,44 @@
+// 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.
+
+// Java method trace dump tool
+
+art_cc_binary {
+    name: "dmtracedump",
+    host_supported: true,
+    device_supported: false,
+    srcs: ["tracedump.cc"],
+    cflags: [
+        "-O0",
+        "-g",
+        "-Wall",
+    ],
+    target: {
+        windows: {
+            enabled: true,
+        },
+    },
+}
+
+art_cc_binary {
+    name: "create_test_dmtrace",
+    host_supported: true,
+    device_supported: false,
+    srcs: ["createtesttrace.cc"],
+    cflags: [
+        "-O0",
+        "-g",
+        "-Wall",
+    ],
+}
diff --git a/tools/dmtracedump/Android.mk b/tools/dmtracedump/Android.mk
deleted file mode 100644
index da0d632..0000000
--- a/tools/dmtracedump/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# 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.
-
-# Java method trace dump tool
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_CPP_EXTENSION := cc
-LOCAL_SRC_FILES := tracedump.cc
-LOCAL_CFLAGS += -O0 -g -Wall
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_MODULE := dmtracedump
-include $(BUILD_HOST_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_CPP_EXTENSION := cc
-LOCAL_SRC_FILES := createtesttrace.cc
-LOCAL_CFLAGS += -O0 -g -Wall
-LOCAL_MODULE := create_test_dmtrace
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/javafuzz/__init__.py b/tools/javafuzz/__init__.py
new file mode 100644
index 0000000..3955c71
--- /dev/null
+++ b/tools/javafuzz/__init__.py
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2016 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.
+#
+
+# This file is intentionally left empty. It indicates that the directory is a Python package.
\ No newline at end of file