Refactor runtime support.

Change-Id: Id7470a4105838150d5ceb73ab2c8c83e739660df
diff --git a/build/Android.common.mk b/build/Android.common.mk
index d09ad63..bc1825e 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -102,18 +102,9 @@
 	src/oatexec.cc
 
 LIBART_COMMON_SRC_FILES := \
-	src/assembler.cc \
-	src/assembler_arm.cc \
-	src/assembler_x86.cc \
 	src/atomic.cc.arm \
-	src/calling_convention.cc \
-	src/calling_convention_arm.cc \
-	src/calling_convention_x86.cc \
 	src/card_table.cc \
 	src/constants.cc \
-	src/context.cc \
-	src/context_arm.cc.arm \
-	src/context_x86.cc \
 	src/check_jni.cc \
 	src/class_linker.cc \
 	src/class_loader.cc \
@@ -165,8 +156,6 @@
 	src/logging.cc \
 	src/mark_stack.cc \
 	src/mark_sweep.cc \
-	src/managed_register_arm.cc \
-	src/managed_register_x86.cc \
 	src/mem_map.cc \
 	src/memory_region.cc \
 	src/monitor.cc \
@@ -184,15 +173,12 @@
 	src/reflection.cc \
 	src/runtime.cc \
 	src/runtime_support.cc \
-	src/runtime_support_common.cc \
 	src/scoped_thread_list_lock.cc \
 	src/signal_catcher.cc \
 	src/space.cc \
 	src/stack.cc \
 	src/stringpiece.cc \
 	src/stringprintf.cc \
-	src/stub_arm.cc \
-	src/stub_x86.cc \
 	src/sun_misc_Unsafe.cc \
 	src/thread.cc \
 	src/thread_list.cc \
@@ -206,6 +192,31 @@
 	src/compiler_llvm/inferred_reg_category_map.cc \
 	src/compiler_llvm/runtime_support_llvm.cc \
 	src/compiler_llvm/utils_llvm.cc
+else
+LIBART_COMMON_SRC_FILES += \
+	src/oat/runtime/arm/stub_arm.cc \
+	src/oat/runtime/context.cc \
+	src/oat/runtime/support_alloc.cc \
+	src/oat/runtime/support_cast.cc \
+	src/oat/runtime/support_debug.cc \
+	src/oat/runtime/support_dexcache.cc \
+	src/oat/runtime/support_field.cc \
+	src/oat/runtime/support_fillarray.cc \
+	src/oat/runtime/support_invoke.cc \
+	src/oat/runtime/support_jni.cc \
+	src/oat/runtime/support_locks.cc \
+	src/oat/runtime/support_math.cc \
+	src/oat/runtime/support_proxy.cc \
+	src/oat/runtime/support_stubs.cc \
+	src/oat/runtime/support_thread.cc \
+	src/oat/runtime/support_throw.cc \
+	src/oat/runtime/support_trace.cc \
+	src/oat/runtime/x86/stub_x86.cc \
+	src/oat/utils/arm/assembler_arm.cc \
+	src/oat/utils/arm/managed_register_arm.cc \
+	src/oat/utils/assembler.cc \
+	src/oat/utils/x86/assembler_x86.cc \
+	src/oat/utils/x86/managed_register_x86.cc
 endif
 
 LIBART_TARGET_SRC_FILES := \
@@ -217,13 +228,24 @@
 	src/thread_android.cc
 
 ifeq ($(TARGET_ARCH),arm)
-LIBART_TARGET_SRC_FILES += src/runtime_support_arm.S src/thread_arm.cc
+LIBART_TARGET_SRC_FILES += \
+	src/oat/runtime/arm/context_arm.cc.arm \
+	src/oat/runtime/arm/oat_support_entrypoints_arm.cc \
+	src/oat/runtime/arm/runtime_support_arm.S \
+	src/thread_arm.cc
 else # TARGET_ARCH != arm
 ifeq ($(TARGET_ARCH),x86)
-LIBART_TARGET_SRC_FILES += src/runtime_support_x86.S src/thread_x86.cc
+LIBART_TARGET_SRC_FILES += \
+	src/oat/runtime/x86/context_x86.cc \
+	src/oat/runtime/x86/oat_support_entrypoints_x86.cc \
+	src/oat/runtime/x86/runtime_support_x86.S \
+	src/thread_x86.cc
 else # TARGET_ARCH != x86
 ifeq ($(TARGET_ARCH),mips)
-LIBART_TARGET_SRC_FILES += src/runtime_support_mips.S src/thread_mips.cc
+LIBART_TARGET_SRC_FILES += \
+	src/oat/runtime/mips/oat_support_entrypoints_mips.cc \
+	src/oat/runtime/mips/runtime_support_mips.S \
+	src/thread_mips.cc
 else # TARGET_ARCH != mips
 $(error unsupported TARGET_ARCH=$(TARGET_ARCH))
 endif # TARGET_ARCH != mips
@@ -238,7 +260,11 @@
 	src/thread_linux.cc
 
 ifeq ($(HOST_ARCH),x86)
-LIBART_HOST_SRC_FILES += src/runtime_support_x86.S src/thread_x86.cc
+LIBART_HOST_SRC_FILES += \
+	src/oat/runtime/x86/oat_support_entrypoints_x86.cc \
+	src/oat/runtime/x86/context_x86.cc \
+	src/oat/runtime/x86/runtime_support_x86.S \
+	src/thread_x86.cc
 else # HOST_ARCH != x86
 $(error unsupported HOST_ARCH=$(HOST_ARCH))
 endif # HOST_ARCH != x86
@@ -262,8 +288,8 @@
 	src/intern_table_test.cc \
 	src/jni_internal_test.cc \
 	src/jni_compiler_test.cc \
-	src/managed_register_arm_test.cc \
-	src/managed_register_x86_test.cc \
+	src/oat/utils/arm/managed_register_arm_test.cc \
+	src/oat/utils/x86/managed_register_x86_test.cc \
 	src/mutex_test.cc \
 	src/oat_test.cc \
 	src/object_test.cc \
@@ -283,7 +309,7 @@
 
 TEST_HOST_SRC_FILES := \
 	$(TEST_COMMON_SRC_FILES) \
-	src/assembler_x86_test.cc
+	src/oat/utils/x86/assembler_x86_test.cc
 
 # subdirectories of test/ which are used as inputs for gtests
 TEST_DEX_DIRECTORIES := \
diff --git a/build/Android.libart-compiler.mk b/build/Android.libart-compiler.mk
index 7140dbd..88b280a 100644
--- a/build/Android.libart-compiler.mk
+++ b/build/Android.libart-compiler.mk
@@ -22,15 +22,18 @@
 	src/compiler/SSATransformation.cc \
 	src/compiler/Utility.cc \
 	src/compiler/codegen/RallocUtil.cc \
-	src/jni_compiler.cc
+	src/oat/jni/calling_convention.cc \
+	src/oat/jni/jni_compiler.cc \
+	src/oat/jni/arm/calling_convention_arm.cc \
+	src/oat/jni/x86/calling_convention_x86.cc
 
 LIBART_COMPILER_ARM_SRC_FILES += \
 	$(LIBART_COMPILER_COMMON_SRC_FILES) \
-	src/jni_internal_arm.cc \
 	src/compiler/codegen/arm/ArchUtility.cc \
 	src/compiler/codegen/arm/ArmRallocUtil.cc \
 	src/compiler/codegen/arm/Assemble.cc \
-	src/compiler/codegen/arm/armv7-a/Codegen.cc
+	src/compiler/codegen/arm/armv7-a/Codegen.cc \
+	src/oat/jni/arm/jni_internal_arm.cc
 
 LIBART_COMPILER_MIPS_SRC_FILES += \
 	$(LIBART_COMPILER_COMMON_SRC_FILES) \
@@ -41,11 +44,11 @@
 
 LIBART_COMPILER_X86_SRC_FILES += \
 	$(LIBART_COMPILER_COMMON_SRC_FILES) \
-	src/jni_internal_x86.cc \
 	src/compiler/codegen/x86/ArchUtility.cc \
 	src/compiler/codegen/x86/X86RallocUtil.cc \
 	src/compiler/codegen/x86/Assemble.cc \
-	src/compiler/codegen/x86/x86/Codegen.cc
+	src/compiler/codegen/x86/x86/Codegen.cc \
+	src/oat/jni/x86/jni_internal_x86.cc
 
 # $(1): target or host
 # $(2): ndebug or debug
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index c9509b7..dd33d1b 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -57,7 +57,7 @@
 $(HOST_CORE_IMG_OUT): $(HOST_CORE_DEX_FILES) $(DEX2OAT_DEPENDENCY)
 	@echo "host dex2oat: $@ ($?)"
 	@mkdir -p $(dir $@)
-	$(hide) $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(HOST_CORE_DEX_FILES)) $(addprefix --dex-location=,$(HOST_CORE_DEX_LOCATIONS)) --oat-file=$(HOST_CORE_OAT_OUT) --oat-location=$(HOST_CORE_OAT) --image=$(HOST_CORE_IMG_OUT) --base=$(IMG_HOST_BASE_ADDRESS) # --instruction-set=X86
+	$(hide) $(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --image-classes=$(PRELOADED_CLASSES) $(addprefix --dex-file=,$(HOST_CORE_DEX_FILES)) $(addprefix --dex-location=,$(HOST_CORE_DEX_LOCATIONS)) --oat-file=$(HOST_CORE_OAT_OUT) --oat-location=$(HOST_CORE_OAT) --image=$(HOST_CORE_IMG_OUT) --base=$(IMG_HOST_BASE_ADDRESS) --instruction-set=X86
 
 $(TARGET_CORE_IMG_OUT): $(TARGET_CORE_DEX_FILES) $(DEX2OAT_DEPENDENCY)
 	@echo "target dex2oat: $@ ($?)"
diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk
index ab10d83..0ccf106 100644
--- a/build/Android.oattest.mk
+++ b/build/Android.oattest.mk
@@ -67,7 +67,7 @@
 .PHONY: test-art-host-oat-$(1)
 test-art-host-oat-$(1): $(ART_TEST_OUT)/oat-test-dex-$(1).jar $(HOST_CORE_IMG_OUT)
 	mkdir -p /tmp/android-data/test-art-host-oat-$(1)
-	$(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --dex-file=$(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar --oat-file=$(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar.oat # --instruction-set=X86
+	$(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --dex-file=$(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar --oat-file=$(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar.oat --instruction-set=X86
 	ANDROID_DATA=/tmp/android-data/test-art-host-oat-$(1) \
 	  ANDROID_ROOT=$(HOST_OUT) \
 	  LD_LIBRARY_PATH=$(HOST_OUT_SHARED_LIBRARIES) \
diff --git a/src/compiler.cc b/src/compiler.cc
index 0bf4673..5507c36 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -22,7 +22,6 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
-#include "assembler.h"
 #include "class_linker.h"
 #include "class_loader.h"
 #include "dex_cache.h"
@@ -1276,7 +1275,7 @@
   uint64_t start_ns = NanoTime();
 
   if ((access_flags & kAccNative) != 0) {
-    compiled_method = (*jni_compiler_)(*this, access_flags, method_idx, class_loader, dex_file);
+    compiled_method = (*jni_compiler_)(*this, access_flags, method_idx, dex_file);
     CHECK(compiled_method != NULL);
   } else if ((access_flags & kAccAbstract) != 0) {
   } else {
diff --git a/src/compiler.h b/src/compiler.h
index 5f4e5ca..fcb9f7f 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -326,7 +326,6 @@
 
   typedef CompiledMethod* (*JniCompilerFn)(Compiler& compiler,
                                            uint32_t access_flags, uint32_t method_idx,
-                                           const ClassLoader* class_loader,
                                            const DexFile& dex_file);
   JniCompilerFn jni_compiler_;
   typedef CompiledInvokeStub* (*CreateInvokeStubFn)(Compiler& compiler, bool is_static,
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index a440555..25fc89e 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -515,7 +515,6 @@
     kThrowDivZero,
     kThrowArrayBounds,
     kThrowVerificationError,
-    kThrowNegArraySize,
     kThrowNoSuchMethod,
     kThrowStackOverflow,
 };
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index 0b0d100..54b8e5f 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "oat/runtime/oat_support_entrypoints.h"
+
 namespace art {
 
 /*
@@ -490,9 +492,9 @@
                                                     cUnit->dex_cache,
                                                     *cUnit->dex_file,
                                                     type_idx)) {
-        funcOffset = OFFSETOF_MEMBER(Thread, pAllocArrayFromCode);
+        funcOffset = ENTRYPOINT_OFFSET(pAllocArrayFromCode);
     } else {
-        funcOffset= OFFSETOF_MEMBER(Thread, pAllocArrayFromCodeWithAccessCheck);
+        funcOffset= ENTRYPOINT_OFFSET(pAllocArrayFromCodeWithAccessCheck);
     }
     callRuntimeHelperImmMethodRegLocation(cUnit, funcOffset, type_idx, rlSrc);
     RegLocation rlResult = oatGetReturn(cUnit, false);
@@ -516,10 +518,9 @@
                                                     cUnit->dex_cache,
                                                     *cUnit->dex_file,
                                                     typeIdx)) {
-        funcOffset = OFFSETOF_MEMBER(Thread, pCheckAndAllocArrayFromCode);
+        funcOffset = ENTRYPOINT_OFFSET(pCheckAndAllocArrayFromCode);
     } else {
-        funcOffset = OFFSETOF_MEMBER(Thread,
-                                  pCheckAndAllocArrayFromCodeWithAccessCheck);
+        funcOffset = ENTRYPOINT_OFFSET(pCheckAndAllocArrayFromCodeWithAccessCheck);
     }
     callRuntimeHelperImmMethodImm(cUnit, funcOffset, typeIdx, elems);
     oatFreeTemp(cUnit, rARG2);
@@ -666,7 +667,7 @@
             LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rBase, 0, NULL);
             loadConstant(cUnit, rARG0, ssbIndex);
             callRuntimeHelperImm(cUnit,
-                                 OFFSETOF_MEMBER(Thread, pInitializeStaticStorage),
+                                 ENTRYPOINT_OFFSET(pInitializeStaticStorage),
                                  ssbIndex);
 #if defined(TARGET_MIPS)
             // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy
@@ -703,9 +704,9 @@
         oatFreeTemp(cUnit, rBase);
     } else {
         oatFlushAllRegs(cUnit);  // Everything to home locations
-        int setterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pSet64Static) :
-                           (isObject ? OFFSETOF_MEMBER(Thread, pSetObjStatic)
-                                     : OFFSETOF_MEMBER(Thread, pSet32Static));
+        int setterOffset = isLongOrDouble ? ENTRYPOINT_OFFSET(pSet64Static) :
+                           (isObject ? ENTRYPOINT_OFFSET(pSetObjStatic)
+                                     : ENTRYPOINT_OFFSET(pSet32Static));
         callRuntimeHelperImmRegLocation(cUnit, setterOffset, fieldIdx, rlSrc);
     }
 }
@@ -763,7 +764,7 @@
             // TUNING: fast path should fall through
             LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rBase, 0, NULL);
             callRuntimeHelperImm(cUnit,
-                                 OFFSETOF_MEMBER(Thread, pInitializeStaticStorage),
+                                 ENTRYPOINT_OFFSET(pInitializeStaticStorage),
                                  ssbIndex);
 #if defined(TARGET_MIPS)
             // For Arm, rRET0 = rARG0 = rBASE, for Mips, we need to copy
@@ -794,9 +795,9 @@
         }
     } else {
         oatFlushAllRegs(cUnit);  // Everything to home locations
-        int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Static) :
-                           (isObject ? OFFSETOF_MEMBER(Thread, pGetObjStatic)
-                                     : OFFSETOF_MEMBER(Thread, pGet32Static));
+        int getterOffset = isLongOrDouble ? ENTRYPOINT_OFFSET(pGet64Static) :
+                           (isObject ? ENTRYPOINT_OFFSET(pGetObjStatic)
+                                     : ENTRYPOINT_OFFSET(pGet32Static));
         callRuntimeHelperImm(cUnit, getterOffset, fieldIdx);
         if (isLongOrDouble) {
             RegLocation rlResult = oatGetReturnWide(cUnit, rlDest.fp);
@@ -817,7 +818,7 @@
 #else
     LIR* branchOver = opCmpImmBranch(cUnit, kCondNe, rINVOKE_TGT, 0, NULL);
     loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pDebugMe), rINVOKE_TGT);
+                 ENTRYPOINT_OFFSET(pDebugMe), rINVOKE_TGT);
     LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
     branchOver->target = (LIR*)target;
 #endif
@@ -825,8 +826,7 @@
 
 void genThrowVerificationError(CompilationUnit* cUnit, MIR* mir)
 {
-    callRuntimeHelperImmImm(cUnit, OFFSETOF_MEMBER(Thread,
-                                              pThrowVerificationErrorFromCode),
+    callRuntimeHelperImmImm(cUnit, ENTRYPOINT_OFFSET(pThrowVerificationErrorFromCode),
                             mir->dalvikInsn.vA, mir->dalvikInsn.vB);
 }
 
@@ -843,10 +843,9 @@
         oatAppendLIR(cUnit, lab);
 #if defined(TARGET_X86)
         opThreadMem(cUnit, kOpBlx,
-                    OFFSETOF_MEMBER(Thread, pTestSuspendFromCode));
+                    ENTRYPOINT_OFFSET(pTestSuspendFromCode));
 #else
-        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                              pTestSuspendFromCode));
+        int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pTestSuspendFromCode));
         opReg(cUnit, kOpBlx, rTgt);
 #endif
         opUnconditionalBranch(cUnit, resumeLab);
@@ -889,7 +888,7 @@
         int v2 = lab->operands[3];
         switch (lab->operands[0]) {
             case kThrowNullPointer:
-                funcOffset = OFFSETOF_MEMBER(Thread, pThrowNullPointerFromCode);
+                funcOffset = ENTRYPOINT_OFFSET(pThrowNullPointerFromCode);
                 break;
             case kThrowArrayBounds:
                 if (v2 != rARG0) {
@@ -910,30 +909,25 @@
                         opRegCopy(cUnit, rARG0, v1);
                     }
                 }
-                funcOffset = OFFSETOF_MEMBER(Thread, pThrowArrayBoundsFromCode);
+                funcOffset = ENTRYPOINT_OFFSET(pThrowArrayBoundsFromCode);
                 break;
             case kThrowDivZero:
-                funcOffset = OFFSETOF_MEMBER(Thread, pThrowDivZeroFromCode);
+                funcOffset = ENTRYPOINT_OFFSET(pThrowDivZeroFromCode);
                 break;
             case kThrowVerificationError:
                 loadConstant(cUnit, rARG0, v1);
                 loadConstant(cUnit, rARG1, v2);
                 funcOffset =
-                    OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode);
-                break;
-            case kThrowNegArraySize:
-                opRegCopy(cUnit, rARG0, v1);
-                funcOffset =
-                    OFFSETOF_MEMBER(Thread, pThrowNegArraySizeFromCode);
+                    ENTRYPOINT_OFFSET(pThrowVerificationErrorFromCode);
                 break;
             case kThrowNoSuchMethod:
                 opRegCopy(cUnit, rARG0, v1);
                 funcOffset =
-                    OFFSETOF_MEMBER(Thread, pThrowNoSuchMethodFromCode);
+                    ENTRYPOINT_OFFSET(pThrowNoSuchMethodFromCode);
                 break;
             case kThrowStackOverflow:
                 funcOffset =
-                    OFFSETOF_MEMBER(Thread, pThrowStackOverflowFromCode);
+                    ENTRYPOINT_OFFSET(pThrowStackOverflowFromCode);
                 // Restore stack alignment
                 opRegImm(cUnit, kOpAdd, rSP,
                          (cUnit->numCoreSpills + cUnit->numFPSpills) * 4);
@@ -1018,9 +1012,9 @@
             storeValue(cUnit, rlDest, rlResult);
         }
     } else {
-        int getterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pGet64Instance) :
-                           (isObject ? OFFSETOF_MEMBER(Thread, pGetObjInstance)
-                                     : OFFSETOF_MEMBER(Thread, pGet32Instance));
+        int getterOffset = isLongOrDouble ? ENTRYPOINT_OFFSET(pGet64Instance) :
+                           (isObject ? ENTRYPOINT_OFFSET(pGetObjInstance)
+                                     : ENTRYPOINT_OFFSET(pGet32Instance));
         callRuntimeHelperImmRegLocation(cUnit, getterOffset, fieldIdx, rlObj);
         if (isLongOrDouble) {
             RegLocation rlResult = oatGetReturnWide(cUnit, rlDest.fp);
@@ -1074,9 +1068,9 @@
             }
         }
     } else {
-        int setterOffset = isLongOrDouble ? OFFSETOF_MEMBER(Thread, pSet64Instance) :
-                           (isObject ? OFFSETOF_MEMBER(Thread, pSetObjInstance)
-                                     : OFFSETOF_MEMBER(Thread, pSet32Instance));
+        int setterOffset = isLongOrDouble ? ENTRYPOINT_OFFSET(pSet64Instance) :
+                           (isObject ? ENTRYPOINT_OFFSET(pSetObjInstance)
+                                     : ENTRYPOINT_OFFSET(pSet32Instance));
         callRuntimeHelperImmRegLocationRegLocation(cUnit, setterOffset,
                                                    fieldIdx, rlObj, rlSrc);
     }
@@ -1096,8 +1090,7 @@
         // Call out to helper which resolves type and verifies access.
         // Resolved type returned in rRET0.
         callRuntimeHelperImmReg(cUnit,
-                                OFFSETOF_MEMBER(Thread,
-                                       pInitializeTypeAndVerifyAccessFromCode),
+                                ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
                                 type_idx, rlMethod.lowReg);
         RegLocation rlResult = oatGetReturn(cUnit, false);
         storeValue(cUnit, rlDest, rlResult);
@@ -1127,8 +1120,7 @@
             // TUNING: move slow path to end & remove unconditional branch
             LIR* target1 = newLIR0(cUnit, kPseudoTargetLabel);
             // Call out to helper, which will return resolved type in rARG0
-            callRuntimeHelperImmReg(cUnit, OFFSETOF_MEMBER(Thread,
-                                                     pInitializeTypeFromCode),
+            callRuntimeHelperImmReg(cUnit, ENTRYPOINT_OFFSET(pInitializeTypeFromCode),
                                     type_idx, rlMethod.lowReg);
             RegLocation rlResult = oatGetReturn(cUnit, false);
             storeValue(cUnit, rlDest, rlResult);
@@ -1165,8 +1157,7 @@
                      Method::DexCacheStringsOffset().Int32Value(), rARG0);
         // Might call out to helper, which will return resolved string in rRET0
 #if !defined(TARGET_X86)
-        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                              pResolveStringFromCode));
+        int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pResolveStringFromCode));
 #endif
         loadWordDisp(cUnit, rRET0, offset_of_string, rARG0);
         loadConstant(cUnit, rARG1, string_idx);
@@ -1188,8 +1179,7 @@
         LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
         branch->target = target;
 #else
-        callRuntimeHelperRegReg(cUnit, OFFSETOF_MEMBER(Thread,
-                                                      pResolveStringFromCode),
+        callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pResolveStringFromCode),
                                 rARG2, rARG1);
 #endif
         genBarrier(cUnit);
@@ -1218,10 +1208,10 @@
     int funcOffset;
     if (cUnit->compiler->CanAccessInstantiableTypeWithoutChecks(
             cUnit->method_idx, cUnit->dex_cache, *cUnit->dex_file, type_idx)) {
-        funcOffset = OFFSETOF_MEMBER(Thread, pAllocObjectFromCode);
+        funcOffset = ENTRYPOINT_OFFSET(pAllocObjectFromCode);
     } else {
         funcOffset =
-            OFFSETOF_MEMBER(Thread, pAllocObjectFromCodeWithAccessCheck);
+            ENTRYPOINT_OFFSET(pAllocObjectFromCodeWithAccessCheck);
     }
     callRuntimeHelperImmMethod(cUnit, funcOffset, type_idx);
     RegLocation rlResult = oatGetReturn(cUnit, false);
@@ -1231,7 +1221,7 @@
 void genThrow(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
 {
     oatFlushAllRegs(cUnit);
-    callRuntimeHelperRegLocation(cUnit, OFFSETOF_MEMBER(Thread, pDeliverException), rlSrc);
+    callRuntimeHelperRegLocation(cUnit, ENTRYPOINT_OFFSET(pDeliverException), rlSrc);
 }
 
 void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
@@ -1250,7 +1240,7 @@
         // Check we have access to type_idx and if not throw IllegalAccessError,
         // returns Class* in rARG0
         callRuntimeHelperImm(cUnit,
-              OFFSETOF_MEMBER(Thread, pInitializeTypeAndVerifyAccessFromCode),
+              ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
               type_idx);
         opRegCopy(cUnit, classReg, rRET0);  // Align usage with fast path
         loadValueDirectFixed(cUnit, rlSrc, rARG0);  // rARG0 <= ref
@@ -1270,8 +1260,7 @@
             LIR* hopBranch = opCmpImmBranch(cUnit, kCondNe, classReg, 0, NULL);
             // Not resolved
             // Call out to helper, which will return resolved type in rRET0
-            callRuntimeHelperImm(cUnit, OFFSETOF_MEMBER(Thread,
-                                                     pInitializeTypeFromCode),
+            callRuntimeHelperImm(cUnit, ENTRYPOINT_OFFSET(pInitializeTypeFromCode),
                                  type_idx);
             opRegCopy(cUnit, rARG2, rRET0); // Align usage with fast path
             loadValueDirectFixed(cUnit, rlSrc, rARG0);  /* reload Ref */
@@ -1288,8 +1277,7 @@
     /* rARG0 is ref, rARG1 is ref->klass_, rARG2 is class */
 #if defined(TARGET_ARM)
     /* Uses conditional nullification */
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                          pInstanceofNonTrivialFromCode));
+    int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
     opRegReg(cUnit, kOpCmp, rARG1, rARG2);  // Same?
     opIT(cUnit, kArmCondEq, "EE");   // if-convert the test
     loadConstant(cUnit, rARG0, 1);       // .eq case - load true
@@ -1301,15 +1289,14 @@
     loadConstant(cUnit, rARG0, 1);       // assume true
     LIR* branchover = opCmpBranch(cUnit, kCondEq, rARG1, rARG2, NULL);
 #if !defined(TARGET_X86)
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                          pInstanceofNonTrivialFromCode));
+    int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
     opRegCopy(cUnit, rARG0, rARG2);        // .ne case - arg0 <= class
     opReg(cUnit, kOpBlx, rTgt);        // .ne case: helper(class, ref->class)
     oatFreeTemp(cUnit, rTgt);
 #else
     opRegCopy(cUnit, rARG0, rARG2);
     opThreadMem(cUnit, kOpBlx,
-                OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode));
+                ENTRYPOINT_OFFSET(pInstanceofNonTrivialFromCode));
 #endif
 #endif
     oatClobberCalleeSave(cUnit);
@@ -1339,8 +1326,7 @@
         // returns Class* in rRET0
         // InitializeTypeAndVerifyAccess(idx, method)
         callRuntimeHelperImmReg(cUnit,
-                                OFFSETOF_MEMBER(Thread,
-                                    pInitializeTypeAndVerifyAccessFromCode),
+                                ENTRYPOINT_OFFSET(pInitializeTypeAndVerifyAccessFromCode),
                                 type_idx, rARG1);
         opRegCopy(cUnit, classReg, rRET0);  // Align usage with fast path
     } else {
@@ -1360,7 +1346,7 @@
             // Call out to helper, which will return resolved type in rARG0
             // InitializeTypeFromCode(idx, method)
             callRuntimeHelperImmReg(cUnit,
-                                    OFFSETOF_MEMBER(Thread, pInitializeTypeFromCode),
+                                    ENTRYPOINT_OFFSET(pInitializeTypeFromCode),
                                     type_idx, rARG1);
             opRegCopy(cUnit, classReg, rARG0); // Align usage with fast path
             // Rejoin code paths
@@ -1378,12 +1364,10 @@
     /* rARG1 now contains object->klass_ */
 #if defined(TARGET_MIPS) || defined(TARGET_X86)
     LIR* branch2 = opCmpBranch(cUnit, kCondEq, rARG1, classReg, NULL);
-    callRuntimeHelperRegReg(cUnit, OFFSETOF_MEMBER(Thread,
-                                                   pCheckCastFromCode),
+    callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pCheckCastFromCode),
                             rARG1, rARG2);
 #else  // defined(TARGET_ARM)
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                          pCheckCastFromCode));
+    int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pCheckCastFromCode));
     opRegReg(cUnit, kOpCmp, rARG1, classReg);
     LIR* branch2 = opCondBranch(cUnit, kCondEq, NULL); /* If eq, trivial yes */
     opRegCopy(cUnit, rARG0, rARG1);
@@ -1418,8 +1402,7 @@
     genNullCheck(cUnit, rlArray.sRegLow, rARG1, mir);
     /* Get the array's class */
     loadWordDisp(cUnit, rARG1, Object::ClassOffset().Int32Value(), rARG1);
-    callRuntimeHelperRegReg(cUnit, OFFSETOF_MEMBER(Thread,
-                                                  pCanPutArrayElementFromCode),
+    callRuntimeHelperRegReg(cUnit, ENTRYPOINT_OFFSET(pCanPutArrayElementFromCode),
                             rARG0, rARG1);
     oatFreeTemp(cUnit, rARG0);
     oatFreeTemp(cUnit, rARG1);
@@ -1725,15 +1708,15 @@
     switch (mir->dalvikInsn.opcode) {
         case Instruction::SHL_LONG:
         case Instruction::SHL_LONG_2ADDR:
-            funcOffset = OFFSETOF_MEMBER(Thread, pShlLong);
+            funcOffset = ENTRYPOINT_OFFSET(pShlLong);
             break;
         case Instruction::SHR_LONG:
         case Instruction::SHR_LONG_2ADDR:
-            funcOffset = OFFSETOF_MEMBER(Thread, pShrLong);
+            funcOffset = ENTRYPOINT_OFFSET(pShrLong);
             break;
         case Instruction::USHR_LONG:
         case Instruction::USHR_LONG_2ADDR:
-            funcOffset = OFFSETOF_MEMBER(Thread, pUshrLong);
+            funcOffset = ENTRYPOINT_OFFSET(pUshrLong);
             break;
         default:
             LOG(FATAL) << "Unexpected case";
@@ -1784,7 +1767,7 @@
             checkZero = true;
             op = kOpDiv;
             callOut = true;
-            funcOffset = OFFSETOF_MEMBER(Thread, pIdiv);
+            funcOffset = ENTRYPOINT_OFFSET(pIdiv);
             retReg = rRET0;
             break;
         /* NOTE: returns in rARG1 */
@@ -1793,7 +1776,7 @@
             checkZero = true;
             op = kOpRem;
             callOut = true;
-            funcOffset = OFFSETOF_MEMBER(Thread, pIdivmod);
+            funcOffset = ENTRYPOINT_OFFSET(pIdivmod);
             retReg = rRET1;
             break;
         case Instruction::AND_INT:
@@ -2108,10 +2091,10 @@
             oatClobber(cUnit, rARG0);
             if ((dalvikOpcode == Instruction::DIV_INT_LIT8) ||
                 (dalvikOpcode == Instruction::DIV_INT_LIT16)) {
-                funcOffset = OFFSETOF_MEMBER(Thread, pIdiv);
+                funcOffset = ENTRYPOINT_OFFSET(pIdiv);
                 isDiv = true;
             } else {
-                funcOffset = OFFSETOF_MEMBER(Thread, pIdivmod);
+                funcOffset = ENTRYPOINT_OFFSET(pIdivmod);
                 isDiv = false;
             }
             callRuntimeHelperRegImm(cUnit, funcOffset, rARG0, lit);
@@ -2173,7 +2156,7 @@
 #elif defined(TARGET_X86)
             callOut = true;
             retReg = rRET0;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLadd);
+            funcOffset = ENTRYPOINT_OFFSET(pLadd);
 #else
             firstOp = kOpAdd;
             secondOp = kOpAdc;
@@ -2186,7 +2169,7 @@
 #elif defined(TARGET_X86)
             callOut = true;
             retReg = rRET0;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLsub);
+            funcOffset = ENTRYPOINT_OFFSET(pLsub);
 #endif
             firstOp = kOpSub;
             secondOp = kOpSbc;
@@ -2195,14 +2178,14 @@
         case Instruction::MUL_LONG_2ADDR:
             callOut = true;
             retReg = rRET0;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLmul);
+            funcOffset = ENTRYPOINT_OFFSET(pLmul);
             break;
         case Instruction::DIV_LONG:
         case Instruction::DIV_LONG_2ADDR:
             callOut = true;
             checkZero = true;
             retReg = rRET0;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLdivmod);
+            funcOffset = ENTRYPOINT_OFFSET(pLdivmod);
             break;
         /* NOTE - result is in rARG2/rARG3 instead of rRET0/rRET1 */
         // FIXME: is true, or could be made true, or other targets?
@@ -2210,7 +2193,7 @@
         case Instruction::REM_LONG_2ADDR:
             callOut = true;
             checkZero = true;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLdivmod);
+            funcOffset = ENTRYPOINT_OFFSET(pLdivmod);
             retReg = rARG2;
             break;
         case Instruction::AND_LONG_2ADDR:
@@ -2218,7 +2201,7 @@
 #if defined(TARGET_X86)
             callOut = true;
             retReg = rRET0;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLand);
+            funcOffset = ENTRYPOINT_OFFSET(pLand);
 #endif
             firstOp = kOpAnd;
             secondOp = kOpAnd;
@@ -2228,7 +2211,7 @@
 #if defined(TARGET_X86)
             callOut = true;
             retReg = rRET0;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLor);
+            funcOffset = ENTRYPOINT_OFFSET(pLor);
 #endif
             firstOp = kOpOr;
             secondOp = kOpOr;
@@ -2238,7 +2221,7 @@
 #if defined(TARGET_X86)
             callOut = true;
             retReg = rRET0;
-            funcOffset = OFFSETOF_MEMBER(Thread, pLxor);
+            funcOffset = ENTRYPOINT_OFFSET(pLxor);
 #endif
             firstOp = kOpXor;
             secondOp = kOpXor;
@@ -2332,23 +2315,23 @@
     switch (mir->dalvikInsn.opcode) {
         case Instruction::ADD_FLOAT_2ADDR:
         case Instruction::ADD_FLOAT:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFadd);
+            funcOffset = ENTRYPOINT_OFFSET(pFadd);
             break;
         case Instruction::SUB_FLOAT_2ADDR:
         case Instruction::SUB_FLOAT:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFsub);
+            funcOffset = ENTRYPOINT_OFFSET(pFsub);
             break;
         case Instruction::DIV_FLOAT_2ADDR:
         case Instruction::DIV_FLOAT:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFdiv);
+            funcOffset = ENTRYPOINT_OFFSET(pFdiv);
             break;
         case Instruction::MUL_FLOAT_2ADDR:
         case Instruction::MUL_FLOAT:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFmul);
+            funcOffset = ENTRYPOINT_OFFSET(pFmul);
             break;
         case Instruction::REM_FLOAT_2ADDR:
         case Instruction::REM_FLOAT:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFmodf);
+            funcOffset = ENTRYPOINT_OFFSET(pFmodf);
             break;
         case Instruction::NEG_FLOAT: {
             genNegFloat(cUnit, rlDest, rlSrc1);
@@ -2375,23 +2358,23 @@
     switch (mir->dalvikInsn.opcode) {
         case Instruction::ADD_DOUBLE_2ADDR:
         case Instruction::ADD_DOUBLE:
-            funcOffset = OFFSETOF_MEMBER(Thread, pDadd);
+            funcOffset = ENTRYPOINT_OFFSET(pDadd);
             break;
         case Instruction::SUB_DOUBLE_2ADDR:
         case Instruction::SUB_DOUBLE:
-            funcOffset = OFFSETOF_MEMBER(Thread, pDsub);
+            funcOffset = ENTRYPOINT_OFFSET(pDsub);
             break;
         case Instruction::DIV_DOUBLE_2ADDR:
         case Instruction::DIV_DOUBLE:
-            funcOffset = OFFSETOF_MEMBER(Thread, pDdiv);
+            funcOffset = ENTRYPOINT_OFFSET(pDdiv);
             break;
         case Instruction::MUL_DOUBLE_2ADDR:
         case Instruction::MUL_DOUBLE:
-            funcOffset = OFFSETOF_MEMBER(Thread, pDmul);
+            funcOffset = ENTRYPOINT_OFFSET(pDmul);
             break;
         case Instruction::REM_DOUBLE_2ADDR:
         case Instruction::REM_DOUBLE:
-            funcOffset = OFFSETOF_MEMBER(Thread, pFmod);
+            funcOffset = ENTRYPOINT_OFFSET(pFmod);
             break;
         case Instruction::NEG_DOUBLE: {
             genNegDouble(cUnit, rlDest, rlSrc1);
@@ -2413,34 +2396,34 @@
 
     switch (opcode) {
         case Instruction::INT_TO_FLOAT:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2f),
+            return genConversionCall(cUnit, mir, ENTRYPOINT_OFFSET(pI2f),
                                      1, 1);
         case Instruction::FLOAT_TO_INT:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2iz),
+            return genConversionCall(cUnit, mir, ENTRYPOINT_OFFSET(pF2iz),
                                      1, 1);
         case Instruction::DOUBLE_TO_FLOAT:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2f),
+            return genConversionCall(cUnit, mir, ENTRYPOINT_OFFSET(pD2f),
                                      2, 1);
         case Instruction::FLOAT_TO_DOUBLE:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pF2d),
+            return genConversionCall(cUnit, mir, ENTRYPOINT_OFFSET(pF2d),
                                      1, 2);
         case Instruction::INT_TO_DOUBLE:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pI2d),
+            return genConversionCall(cUnit, mir, ENTRYPOINT_OFFSET(pI2d),
                                      1, 2);
         case Instruction::DOUBLE_TO_INT:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pD2iz),
+            return genConversionCall(cUnit, mir, ENTRYPOINT_OFFSET(pD2iz),
                                      2, 1);
         case Instruction::FLOAT_TO_LONG:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
-                                     pF2l), 1, 2);
+            return genConversionCall(cUnit, mir, ENTRYPOINT_OFFSET(pF2l),
+                                     1, 2);
         case Instruction::LONG_TO_FLOAT:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2f),
+            return genConversionCall(cUnit, mir, ENTRYPOINT_OFFSET(pL2f),
                                      2, 1);
         case Instruction::DOUBLE_TO_LONG:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread,
-                                     pD2l), 2, 2);
+            return genConversionCall(cUnit, mir, ENTRYPOINT_OFFSET(pD2l),
+                                     2, 2);
         case Instruction::LONG_TO_DOUBLE:
-            return genConversionCall(cUnit, mir, OFFSETOF_MEMBER(Thread, pL2d),
+            return genConversionCall(cUnit, mir, ENTRYPOINT_OFFSET(pL2d),
                                      2, 2);
         default:
             return true;
@@ -2492,12 +2475,11 @@
 #if defined(TARGET_X86)
         UNIMPLEMENTED(FATAL);
 #else
-        int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                              pTestSuspendFromCode));
+        int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pTestSuspendFromCode));
         opReg(cUnit, kOpBlx, rTgt);
         // Refresh rSUSPEND
         loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pUpdateDebuggerFromCode),
+                     ENTRYPOINT_OFFSET(pUpdateDebuggerFromCode),
                      rSUSPEND);
 #endif
     } else {
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index e4feb4d..8a9d1f5 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "oat/runtime/oat_support_entrypoints.h"
+
 namespace art {
 
 /*
@@ -301,7 +303,7 @@
                          uintptr_t unused, uintptr_t unused2,
                          InvokeType unused3)
 {
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeStaticTrampolineWithAccessCheck);
+  int trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
   return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
 }
 
@@ -309,7 +311,7 @@
                          uint32_t dexIdx, uint32_t methodIdx, uintptr_t unused,
                          uintptr_t unused2, InvokeType unused3)
 {
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeDirectTrampolineWithAccessCheck);
+  int trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
   return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
 }
 
@@ -317,7 +319,7 @@
                         uint32_t dexIdx, uint32_t methodIdx, uintptr_t unused,
                         uintptr_t unused2, InvokeType unused3)
 {
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeSuperTrampolineWithAccessCheck);
+  int trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
   return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
 }
 
@@ -325,7 +327,7 @@
                     uint32_t dexIdx, uint32_t methodIdx, uintptr_t unused,
                     uintptr_t unused2, InvokeType unused3)
 {
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeVirtualTrampolineWithAccessCheck);
+  int trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
   return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
 }
 
@@ -337,7 +339,7 @@
                           uint32_t dexIdx, uint32_t unused, uintptr_t unused2,
                           uintptr_t unused3, InvokeType unused4)
 {
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampoline);
+  int trampoline = ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline);
   return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
 }
 
@@ -346,7 +348,7 @@
                                          uint32_t unused, uintptr_t unused2,
                                          uintptr_t unused3, InvokeType unused4)
 {
-  int trampoline = OFFSETOF_MEMBER(Thread, pInvokeInterfaceTrampolineWithAccessCheck);
+  int trampoline = ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
   return nextInvokeInsnSP(cUnit, mir, trampoline, state, dexIdx, 0);
 }
 
@@ -553,14 +555,14 @@
     // Generate memcpy
     opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset);
     opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
-    callRuntimeHelperRegRegImm(cUnit, OFFSETOF_MEMBER(Thread, pMemcpy),
+    callRuntimeHelperRegRegImm(cUnit, ENTRYPOINT_OFFSET(pMemcpy),
                                rARG0, rARG1, (numArgs - 3) * 4);
 #else
     if (numArgs >= 20) {
         // Generate memcpy
         opRegRegImm(cUnit, kOpAdd, rARG0, rSP, outsOffset);
         opRegRegImm(cUnit, kOpAdd, rARG1, rSP, startOffset);
-        callRuntimeHelperRegRegImm(cUnit, OFFSETOF_MEMBER(Thread, pMemcpy),
+        callRuntimeHelperRegRegImm(cUnit, ENTRYPOINT_OFFSET(pMemcpy),
                                    rARG0, rARG1, (numArgs - 3) * 4);
     } else {
         // Use vldm/vstm pair using rARG3 as a temp
@@ -820,7 +822,7 @@
     } else {
         loadValueDirectFixed(cUnit, rlStart, regStart);
     }
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pIndexOf));
+    int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pIndexOf));
     genNullCheck(cUnit, rlObj.sRegLow, regPtr, mir);
     LIR* launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (int)mir, type);
     oatInsertGrowableList(cUnit, &cUnit->intrinsicLaunchpads,
@@ -852,7 +854,7 @@
     RegLocation rlCmp = oatGetSrc(cUnit, mir, 1);
     loadValueDirectFixed(cUnit, rlThis, regThis);
     loadValueDirectFixed(cUnit, rlCmp, regCmp);
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pStringCompareTo));
+    int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pStringCompareTo));
     genNullCheck(cUnit, rlThis.sRegLow, regThis, mir);
     //TUNING: check if rlCmp.sRegLow is already null checked
     LIR* launchPad = rawLIR(cUnit, 0, kPseudoIntrinsicRetry, (int)mir, type);
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index c24b856..9326faf 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -22,6 +22,8 @@
  *
  */
 
+#include "oat/runtime/oat_support_entrypoints.h"
+
 namespace art {
 
 void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset);
@@ -112,7 +114,7 @@
     if (cUnit->genDebugger) {
         // Refresh update debugger callout
         loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pUpdateDebuggerFromCode), rSUSPEND);
+                     ENTRYPOINT_OFFSET(pUpdateDebuggerFromCode), rSUSPEND);
         genDebuggerUpdate(cUnit, DEBUGGER_METHOD_ENTRY);
     }
 
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 4319ec8..9477d2c 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -23,6 +23,7 @@
  */
 
 #include "oat_compilation_unit.h"
+#include "oat/runtime/oat_support_entrypoints.h"
 
 namespace art {
 
@@ -491,7 +492,7 @@
     oatFlushAllRegs(cUnit);   /* Everything to home location */
     loadValueDirectFixed(cUnit, rlSrc, r0);
     loadWordDisp(cUnit, rSELF,
-                 OFFSETOF_MEMBER(Thread, pHandleFillArrayDataFromCode), rLR);
+                 ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode), rLR);
     // Materialize a pointer to the fill data image
     newLIR3(cUnit, kThumb2Adr, r1, 0, (intptr_t)tabRec);
     oatClobberCalleeSave(cUnit);
@@ -565,7 +566,7 @@
     opRegImm(cUnit, kOpCmp, r1, 0);
     opIT(cUnit, kArmCondNe, "T");
     // Go expensive route - artLockObjectFromCode(self, obj);
-    loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pLockObjectFromCode),
+    loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pLockObjectFromCode),
                  rLR);
     oatClobberCalleeSave(cUnit);
     opReg(cUnit, kOpBlx, rLR);
@@ -596,7 +597,7 @@
     opIT(cUnit, kArmCondEq, "EE");
     storeWordDisp(cUnit, r0, Object::MonitorOffset().Int32Value(), r3);
     // Go expensive route - UnlockObjectFromCode(obj);
-    loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pUnlockObjectFromCode),
+    loadWordDisp(cUnit, rSELF, ENTRYPOINT_OFFSET(pUnlockObjectFromCode),
                  rLR);
     oatClobberCalleeSave(cUnit);
     opReg(cUnit, kOpBlx, rLR);
diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc
index b7f055d..5e41400 100644
--- a/src/compiler/codegen/mips/ArchFactory.cc
+++ b/src/compiler/codegen/mips/ArchFactory.cc
@@ -22,6 +22,8 @@
  *
  */
 
+#include "oat/runtime/oat_support_entrypoints.h"
+
 namespace art {
 
 bool genAddLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
@@ -191,7 +193,7 @@
     if (cUnit->genDebugger) {
         // Refresh update debugger callout
         loadWordDisp(cUnit, rSELF,
-                     OFFSETOF_MEMBER(Thread, pUpdateDebuggerFromCode), rSUSPEND);
+                     ENTRYPOINT_OFFSET(pUpdateDebuggerFromCode), rSUSPEND);
         genDebuggerUpdate(cUnit, DEBUGGER_METHOD_ENTRY);
     }
 
diff --git a/src/compiler/codegen/mips/FP/MipsFP.cc b/src/compiler/codegen/mips/FP/MipsFP.cc
index 6524641..948ded6 100644
--- a/src/compiler/codegen/mips/FP/MipsFP.cc
+++ b/src/compiler/codegen/mips/FP/MipsFP.cc
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "oat/runtime/oat_support_entrypoints.h"
+
 namespace art {
 
 bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
@@ -191,18 +193,18 @@
 
     switch (mir->dalvikInsn.opcode) {
         case Instruction::CMPL_FLOAT:
-            offset = OFFSETOF_MEMBER(Thread, pCmplFloat);
+            offset = ENTRYPOINT_OFFSET(pCmplFloat);
             wide = false;
             break;
         case Instruction::CMPG_FLOAT:
-            offset = OFFSETOF_MEMBER(Thread, pCmpgFloat);
+            offset = ENTRYPOINT_OFFSET(pCmpgFloat);
             wide = false;
             break;
         case Instruction::CMPL_DOUBLE:
-            offset = OFFSETOF_MEMBER(Thread, pCmplDouble);
+            offset = ENTRYPOINT_OFFSET(pCmplDouble);
             break;
         case Instruction::CMPG_DOUBLE:
-            offset = OFFSETOF_MEMBER(Thread, pCmpgDouble);
+            offset = ENTRYPOINT_OFFSET(pCmpgDouble);
             break;
         default:
             return true;
diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc
index bf65ba6..b810f98 100644
--- a/src/compiler/codegen/mips/Mips32/Gen.cc
+++ b/src/compiler/codegen/mips/Mips32/Gen.cc
@@ -22,6 +22,8 @@
  *
  */
 
+#include "oat/runtime/oat_support_entrypoints.h"
+
 namespace art {
 
 void genSpecialCase(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
@@ -245,8 +247,7 @@
     genBarrier(cUnit);
     newLIR0(cUnit, kMipsCurrPC);  // Really a jal to .+8
     // Now, fill the branch delay slot with the helper load
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread,
-                          pHandleFillArrayDataFromCode));
+    int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pHandleFillArrayDataFromCode));
     genBarrier(cUnit);  // Scheduling barrier
 
     // Construct BaseLabel and set up table base register
@@ -291,7 +292,7 @@
     oatLockCallTemps(cUnit);  // Prepare for explicit register usage
     genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir);
     // Go expensive route - artLockObjectFromCode(self, obj);
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pLockObjectFromCode));
+    int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pLockObjectFromCode));
     oatClobberCalleeSave(cUnit);
     opReg(cUnit, kOpBlx, rTgt);
 }
@@ -306,7 +307,7 @@
     oatLockCallTemps(cUnit);  // Prepare for explicit register usage
     genNullCheck(cUnit, rlSrc.sRegLow, rARG0, mir);
     // Go expensive route - UnlockObjectFromCode(obj);
-    int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, pUnlockObjectFromCode));
+    int rTgt = loadHelper(cUnit, ENTRYPOINT_OFFSET(pUnlockObjectFromCode));
     oatClobberCalleeSave(cUnit);
     opReg(cUnit, kOpBlx, rTgt);
 }
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index ff4123a..0a203e9 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -64,35 +64,6 @@
 // Exception
 //----------------------------------------------------------------------------
 
-static std::string MethodNameFromIndex(const Method* method,
-                                       uint32_t ref,
-                                       verifier::VerifyErrorRefType ref_type,
-                                       bool access) {
-  CHECK_EQ(static_cast<int>(ref_type),
-           static_cast<int>(verifier::VERIFY_ERROR_REF_METHOD));
-
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  const DexFile& dex_file =
-      class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
-
-  const DexFile::MethodId& id = dex_file.GetMethodId(ref);
-  std::string class_name(
-      PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id))
-                         );
-  const char* method_name = dex_file.StringDataByIdx(id.name_idx_);
-  if (!access) {
-    return class_name + "." + method_name;
-  }
-
-  std::string result;
-  result += "tried to access method ";
-  result += class_name + "." + method_name + ":" +
-      dex_file.CreateMethodSignature(id.proto_idx_, NULL);
-  result += " from class ";
-  result += PrettyDescriptor(method->GetDeclaringClass());
-  return result;
-}
-
 bool art_is_exception_pending_from_code() {
   return Thread::Current()->IsExceptionPending();
 }
diff --git a/src/debugger.cc b/src/debugger.cc
index 5a9a462..70f9c8e 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -23,7 +23,7 @@
 #include "class_linker.h"
 #include "class_loader.h"
 #include "dex_verifier.h" // For Instruction.
-#include "context.h"
+#include "oat/runtime/context.h"
 #include "object_utils.h"
 #include "ScopedLocalRef.h"
 #include "ScopedPrimitiveArray.h"
diff --git a/src/exception_test.cc b/src/exception_test.cc
index 3c2235a..e52992c 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -17,7 +17,6 @@
 #include <sys/mman.h>
 
 #include "UniquePtr.h"
-#include "assembler.h"
 #include "class_linker.h"
 #include "common_test.h"
 #include "dex_file.h"
diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc
index 7a78814..a61bc9f 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -17,7 +17,6 @@
 #include <sys/mman.h>
 
 #include "UniquePtr.h"
-#include "assembler.h"
 #include "class_linker.h"
 #include "common_test.h"
 #include "dex_file.h"
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index dba933a..949217b 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -26,7 +26,6 @@
 
 #include "ScopedLocalRef.h"
 #include "UniquePtr.h"
-#include "assembler.h"
 #include "class_linker.h"
 #include "class_loader.h"
 #include "jni.h"
diff --git a/src/calling_convention_arm.cc b/src/oat/jni/arm/calling_convention_arm.cc
similarity index 98%
rename from src/calling_convention_arm.cc
rename to src/oat/jni/arm/calling_convention_arm.cc
index 924b291..75c0380 100644
--- a/src/calling_convention_arm.cc
+++ b/src/oat/jni/arm/calling_convention_arm.cc
@@ -16,7 +16,7 @@
 
 #include "calling_convention_arm.h"
 #include "logging.h"
-#include "managed_register_arm.h"
+#include "oat/utils/arm/managed_register_arm.h"
 
 namespace art {
 namespace arm {
diff --git a/src/calling_convention_arm.h b/src/oat/jni/arm/calling_convention_arm.h
similarity index 93%
rename from src/calling_convention_arm.h
rename to src/oat/jni/arm/calling_convention_arm.h
index f03429f..cb1d6a9 100644
--- a/src/calling_convention_arm.h
+++ b/src/oat/jni/arm/calling_convention_arm.h
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_CALLING_CONVENTION_ARM_H_
-#define ART_SRC_CALLING_CONVENTION_ARM_H_
+#ifndef ART_SRC_OAT_JNI_ARM_CALLING_CONVENTION_ARM_H_
+#define ART_SRC_OAT_JNI_ARM_CALLING_CONVENTION_ARM_H_
 
-#include "calling_convention.h"
+#include "oat/jni/calling_convention.h"
 
 namespace art {
 namespace arm {
@@ -87,4 +87,4 @@
 }  // namespace arm
 }  // namespace art
 
-#endif  // ART_SRC_CALLING_CONVENTION_ARM_H_
+#endif  // ART_SRC_OAT_JNI_ARM_CALLING_CONVENTION_ARM_H_
diff --git a/src/jni_internal_arm.cc b/src/oat/jni/arm/jni_internal_arm.cc
similarity index 96%
rename from src/jni_internal_arm.cc
rename to src/oat/jni/arm/jni_internal_arm.cc
index 476c623..2227742 100644
--- a/src/jni_internal_arm.cc
+++ b/src/oat/jni/arm/jni_internal_arm.cc
@@ -19,9 +19,10 @@
 #include <algorithm>
 
 #include "asm_support.h"
-#include "assembler.h"
 #include "compiled_method.h"
 #include "compiler.h"
+#include "oat/utils/arm/assembler_arm.h"
+#include "oat/utils/assembler.h"
 #include "object.h"
 
 namespace art {
@@ -162,6 +163,7 @@
 }  // namespace arm
 }  // namespace art
 
-extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& compiler, bool is_static, const char* shorty, uint32_t shorty_len) {
+extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& /*compiler*/, bool is_static,
+                                                        const char* shorty, uint32_t shorty_len) {
   return art::arm::CreateInvokeStub(is_static, shorty, shorty_len);
 }
diff --git a/src/calling_convention.cc b/src/oat/jni/calling_convention.cc
similarity index 97%
rename from src/calling_convention.cc
rename to src/oat/jni/calling_convention.cc
index 396c9dd..e7b9cc8 100644
--- a/src/calling_convention.cc
+++ b/src/oat/jni/calling_convention.cc
@@ -16,8 +16,8 @@
 
 #include "calling_convention.h"
 
-#include "calling_convention_arm.h"
-#include "calling_convention_x86.h"
+#include "oat/jni/arm/calling_convention_arm.h"
+#include "oat/jni/x86/calling_convention_x86.h"
 #include "logging.h"
 #include "utils.h"
 
diff --git a/src/calling_convention.h b/src/oat/jni/calling_convention.h
similarity index 97%
rename from src/calling_convention.h
rename to src/oat/jni/calling_convention.h
index 3a0eb5a..7e42904 100644
--- a/src/calling_convention.h
+++ b/src/oat/jni/calling_convention.h
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_CALLING_CONVENTION_H_
-#define ART_SRC_CALLING_CONVENTION_H_
+#ifndef ART_SRC_OAT_JNI_CALLING_CONVENTION_H_
+#define ART_SRC_OAT_JNI_CALLING_CONVENTION_H_
 
 #include <vector>
-#include "managed_register.h"
+#include "oat/utils/managed_register.h"
 #include "stack_indirect_reference_table.h"
 #include "thread.h"
 
@@ -284,4 +284,4 @@
 
 }  // namespace art
 
-#endif  // ART_SRC_CALLING_CONVENTION_H_
+#endif  // ART_SRC_OAT_JNI_CALLING_CONVENTION_H_
diff --git a/src/jni_compiler.cc b/src/oat/jni/jni_compiler.cc
similarity index 98%
rename from src/jni_compiler.cc
rename to src/oat/jni/jni_compiler.cc
index 08d3109..30341c2 100644
--- a/src/jni_compiler.cc
+++ b/src/oat/jni/jni_compiler.cc
@@ -17,7 +17,6 @@
 #include <sys/mman.h>
 #include <vector>
 
-#include "assembler.h"
 #include "calling_convention.h"
 #include "class_linker.h"
 #include "compiled_method.h"
@@ -26,7 +25,9 @@
 #include "jni_internal.h"
 #include "logging.h"
 #include "macros.h"
-#include "managed_register.h"
+#include "oat/runtime/oat_support_entrypoints.h"
+#include "oat/utils/assembler.h"
+#include "oat/utils/managed_register.h"
 #include "thread.h"
 #include "UniquePtr.h"
 
@@ -171,7 +172,6 @@
 //
 CompiledMethod* ArtJniCompileMethodInternal(Compiler& compiler,
                                             uint32_t access_flags, uint32_t method_idx,
-                                            const ClassLoader* class_loader,
                                             const DexFile& dex_file) {
   CHECK((access_flags & kAccNative) != 0);
   const bool is_static = (access_flags & kAccStatic) != 0;
@@ -505,12 +505,12 @@
     if (jni_conv->IsCurrentParamInRegister()) {
       __ GetCurrentThread(jni_conv->CurrentParamRegister());
       __ Call(jni_conv->CurrentParamRegister(),
-              Offset(OFFSETOF_MEMBER(Thread, pDecodeJObjectInThread)),
+              Offset(ENTRYPOINT_OFFSET(pDecodeJObjectInThread)),
               jni_conv->InterproceduralScratchRegister());
     } else {
       __ GetCurrentThread(jni_conv->CurrentParamStackOffset(),
                           jni_conv->InterproceduralScratchRegister());
-      __ Call(ThreadOffset(OFFSETOF_MEMBER(Thread, pDecodeJObjectInThread)),
+      __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pDecodeJObjectInThread)),
               jni_conv->InterproceduralScratchRegister());
     }
 
@@ -565,7 +565,6 @@
 
 extern "C" art::CompiledMethod* ArtJniCompileMethod(art::Compiler& compiler,
                                                     uint32_t access_flags, uint32_t method_idx,
-                                                    const art::ClassLoader* class_loader,
                                                     const art::DexFile& dex_file) {
-  return ArtJniCompileMethodInternal(compiler, access_flags, method_idx, class_loader, dex_file);
+  return ArtJniCompileMethodInternal(compiler, access_flags, method_idx, dex_file);
 }
diff --git a/src/calling_convention_x86.cc b/src/oat/jni/x86/calling_convention_x86.cc
similarity index 98%
rename from src/calling_convention_x86.cc
rename to src/oat/jni/x86/calling_convention_x86.cc
index 15f4495..1f66d71 100644
--- a/src/calling_convention_x86.cc
+++ b/src/oat/jni/x86/calling_convention_x86.cc
@@ -15,8 +15,9 @@
  */
 
 #include "calling_convention_x86.h"
+
 #include "logging.h"
-#include "managed_register_x86.h"
+#include "oat/utils/x86/managed_register_x86.h"
 #include "utils.h"
 
 namespace art {
diff --git a/src/calling_convention_x86.h b/src/oat/jni/x86/calling_convention_x86.h
similarity index 92%
rename from src/calling_convention_x86.h
rename to src/oat/jni/x86/calling_convention_x86.h
index 4bca318..e32b8fd 100644
--- a/src/calling_convention_x86.h
+++ b/src/oat/jni/x86/calling_convention_x86.h
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_CALLING_CONVENTION_X86_H_
-#define ART_SRC_CALLING_CONVENTION_X86_H_
+#ifndef ART_SRC_OAT_JNI_X86_CALLING_CONVENTION_X86_H_
+#define ART_SRC_OAT_JNI_X86_CALLING_CONVENTION_X86_H_
 
-#include "calling_convention.h"
+#include "oat/jni/calling_convention.h"
 
 namespace art {
 namespace x86 {
@@ -83,4 +83,4 @@
 }  // namespace x86
 }  // namespace art
 
-#endif  // ART_SRC_CALLING_CONVENTION_X86_H_
+#endif  // ART_SRC_OAT_JNI_X86_CALLING_CONVENTION_X86_H_
diff --git a/src/jni_internal_x86.cc b/src/oat/jni/x86/jni_internal_x86.cc
similarity index 96%
rename from src/jni_internal_x86.cc
rename to src/oat/jni/x86/jni_internal_x86.cc
index 86d7749..6abeb49 100644
--- a/src/jni_internal_x86.cc
+++ b/src/oat/jni/x86/jni_internal_x86.cc
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-#include "assembler.h"
 #include "compiled_method.h"
 #include "compiler.h"
+#include "oat/utils/assembler.h"
+#include "oat/utils/x86/assembler_x86.h"
 #include "object.h"
 
 namespace art {
@@ -162,6 +163,7 @@
 }  // namespace x86
 }  // namespace art
 
-extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& compiler, bool is_static, const char* shorty, uint32_t shorty_len) {
+extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& /*compiler*/, bool is_static,
+                                                        const char* shorty, uint32_t shorty_len) {
   return art::x86::CreateInvokeStub(is_static, shorty, shorty_len);
 }
diff --git a/src/context_arm.cc b/src/oat/runtime/arm/context_arm.cc
similarity index 95%
rename from src/context_arm.cc
rename to src/oat/runtime/arm/context_arm.cc
index d0bc6c7..28f1db9 100644
--- a/src/context_arm.cc
+++ b/src/oat/runtime/arm/context_arm.cc
@@ -17,7 +17,6 @@
 #include "context_arm.h"
 
 #include "object.h"
-#include "runtime_support.h"
 
 namespace art {
 namespace arm {
@@ -62,12 +61,10 @@
   }
 }
 
+extern "C" void art_do_long_jump(uint32_t*, uint32_t*);
+
 void ArmContext::DoLongJump() {
-#if defined(__arm__)
   art_do_long_jump(&gprs_[0], &fprs_[S0]);
-#else
-  UNIMPLEMENTED(FATAL);
-#endif
 }
 
 }  // namespace arm
diff --git a/src/context_arm.h b/src/oat/runtime/arm/context_arm.h
similarity index 86%
rename from src/context_arm.h
rename to src/oat/runtime/arm/context_arm.h
index 9ee0754..216d282 100644
--- a/src/context_arm.h
+++ b/src/oat/runtime/arm/context_arm.h
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_CONTEXT_ARM_H_
-#define ART_SRC_CONTEXT_ARM_H_
+#ifndef ART_SRC_OAT_RUNTIME_ARM_CONTEXT_ARM_H_
+#define ART_SRC_OAT_RUNTIME_ARM_CONTEXT_ARM_H_
 
 #include "constants_arm.h"
-#include "context.h"
+#include "oat/runtime/context.h"
 
 namespace art {
 namespace arm {
@@ -54,4 +54,4 @@
 }  // namespace arm
 }  // namespace art
 
-#endif  // ART_SRC_CONTEXT_ARM_H_
+#endif  // ART_SRC_OAT_RUNTIME_ARM_CONTEXT_ARM_H_
diff --git a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
new file mode 100644
index 0000000..fcff424
--- /dev/null
+++ b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
@@ -0,0 +1,275 @@
+/*
+ * 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 "oat/runtime/oat_support_entrypoints.h"
+
+namespace art {
+
+// Alloc entrypoints.
+extern "C" void* art_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_alloc_object_from_code(uint32_t type_idx, void* method);
+extern "C" void* art_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
+extern "C" void* art_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+
+// Cast entrypoints.
+extern uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class);
+extern "C" void art_can_put_array_element_from_code(void*, void*);
+extern "C" void art_check_cast_from_code(void*, void*);
+
+// Debug entrypoints.
+extern void DebugMe(Method* method, uint32_t info);
+extern "C" void art_update_debugger(void*, void*, int32_t, void*);
+
+// DexCache entrypoints.
+extern "C" void* art_initialize_static_storage_from_code(uint32_t, void*);
+extern "C" void* art_initialize_type_from_code(uint32_t, void*);
+extern "C" void* art_initialize_type_and_verify_access_from_code(uint32_t, void*);
+extern "C" void* art_resolve_string_from_code(void*, uint32_t);
+
+// Field entrypoints.
+extern "C" int art_set32_instance_from_code(uint32_t, void*, int32_t);
+extern "C" int art_set32_static_from_code(uint32_t, int32_t);
+extern "C" int art_set64_instance_from_code(uint32_t, void*, int64_t);
+extern "C" int art_set64_static_from_code(uint32_t, int64_t);
+extern "C" int art_set_obj_instance_from_code(uint32_t, void*, void*);
+extern "C" int art_set_obj_static_from_code(uint32_t, void*);
+extern "C" int32_t art_get32_instance_from_code(uint32_t, void*);
+extern "C" int32_t art_get32_static_from_code(uint32_t);
+extern "C" int64_t art_get64_instance_from_code(uint32_t, void*);
+extern "C" int64_t art_get64_static_from_code(uint32_t);
+extern "C" void* art_get_obj_instance_from_code(uint32_t, void*);
+extern "C" void* art_get_obj_static_from_code(uint32_t);
+
+// FillArray entrypoint.
+extern "C" void art_handle_fill_data_from_code(void*, void*);
+
+// JNI entrypoints.
+extern Object* DecodeJObjectInThread(Thread* thread, jobject obj);
+extern void* FindNativeMethod(Thread* thread);
+
+// Lock entrypoints.
+extern "C" void art_lock_object_from_code(void*);
+extern "C" void art_unlock_object_from_code(void*);
+
+// Math entrypoints.
+extern int32_t CmpgDouble(double a, double b);
+extern int32_t CmplDouble(double a, double b);
+extern int32_t CmpgFloat(float a, float b);
+extern int32_t CmplFloat(float a, float b);
+
+// Math conversions.
+extern "C" float __aeabi_i2f(int32_t op1);         // INT_TO_FLOAT
+extern "C" int32_t __aeabi_f2iz(float op1);        // FLOAT_TO_INT
+extern "C" float __aeabi_d2f(double op1);          // DOUBLE_TO_FLOAT
+extern "C" double __aeabi_f2d(float op1);          // FLOAT_TO_DOUBLE
+extern "C" double __aeabi_i2d(int32_t op1);        // INT_TO_DOUBLE
+extern "C" int32_t __aeabi_d2iz(double op1);       // DOUBLE_TO_INT
+extern "C" float __aeabi_l2f(int64_t op1);         // LONG_TO_FLOAT
+extern "C" double __aeabi_l2d(int64_t op1);        // LONG_TO_DOUBLE
+extern int64_t D2L(double d);
+extern int64_t F2L(float f);
+
+// Single-precision FP arithmetics.
+extern "C" float __aeabi_fadd(float a, float b);   // ADD_FLOAT[_2ADDR]
+extern "C" float __aeabi_fsub(float a, float b);   // SUB_FLOAT[_2ADDR]
+extern "C" float __aeabi_fdiv(float a, float b);   // DIV_FLOAT[_2ADDR]
+extern "C" float __aeabi_fmul(float a, float b);   // MUL_FLOAT[_2ADDR]
+extern "C" float fmodf(float a, float b);          // REM_FLOAT[_2ADDR]
+
+// Double-precision FP arithmetics.
+extern "C" double __aeabi_dadd(double a, double b); // ADD_DOUBLE[_2ADDR]
+extern "C" double __aeabi_dsub(double a, double b); // SUB_DOUBLE[_2ADDR]
+extern "C" double __aeabi_ddiv(double a, double b); // DIV_DOUBLE[_2ADDR]
+extern "C" double __aeabi_dmul(double a, double b); // MUL_DOUBLE[_2ADDR]
+extern "C" double fmod(double a, double b);         // REM_DOUBLE[_2ADDR]
+
+// Integer arithmetics.
+extern "C" int __aeabi_idivmod(int32_t op1, int32_t op2);  // REM_INT[_2ADDR|_LIT8|_LIT16]
+extern "C" int __aeabi_idiv(int32_t op1, int32_t op2);     // DIV_INT[_2ADDR|_LIT8|_LIT16]
+
+// Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR]
+extern "C" long long __aeabi_ldivmod(long long op1, long long op2);
+extern "C" long long __aeabi_lmul(long long op1, long long op2);
+extern "C" uint64_t art_shl_long(uint64_t, uint32_t);
+extern "C" uint64_t art_shr_long(uint64_t, uint32_t);
+extern "C" uint64_t art_ushr_long(uint64_t, uint32_t);
+
+// Intrinsic entrypoints.
+extern "C" int32_t __memcmp16(void*, void*, int32_t);
+extern "C" int32_t art_indexof(void*, uint32_t, uint32_t, uint32_t);
+extern "C" int32_t art_string_compareto(void*, void*);
+
+// Invoke entrypoints.
+const void* UnresolvedDirectMethodTrampolineFromCode(Method*, Method**, Thread*,
+                                                     Runtime::TrampolineType);
+extern "C" void art_invoke_direct_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_interface_trampoline(uint32_t, void*);
+extern "C" void art_invoke_interface_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_static_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_super_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
+
+// Thread entrypoints.
+extern void CheckSuspendFromCode(Thread* thread);
+extern "C" void art_test_suspend();
+
+// Throw entrypoints.
+extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
+extern "C" void art_deliver_exception_from_code(void*);
+extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
+extern "C" void art_throw_div_zero_from_code();
+extern "C" void art_throw_no_such_method_from_code(int32_t method_idx);
+extern "C" void art_throw_null_pointer_exception_from_code();
+extern "C" void art_throw_stack_overflow_from_code(void*);
+extern "C" void art_throw_verification_error_from_code(int32_t src1, int32_t ref);
+
+// Trace entrypoints.
+extern "C" void art_trace_entry_from_code(void*);
+extern "C" void art_trace_exit_from_code();
+
+void InitEntryPoints(EntryPoints* points) {
+  // Alloc
+  points->pAllocArrayFromCode = art_alloc_array_from_code;
+  points->pAllocArrayFromCodeWithAccessCheck = art_alloc_array_from_code_with_access_check;
+  points->pAllocObjectFromCode = art_alloc_object_from_code;
+  points->pAllocObjectFromCodeWithAccessCheck = art_alloc_object_from_code_with_access_check;
+  points->pCheckAndAllocArrayFromCode = art_check_and_alloc_array_from_code;
+  points->pCheckAndAllocArrayFromCodeWithAccessCheck = art_check_and_alloc_array_from_code_with_access_check;
+
+  // Cast
+  points->pInstanceofNonTrivialFromCode = IsAssignableFromCode;
+  points->pCanPutArrayElementFromCode = art_can_put_array_element_from_code;
+  points->pCheckCastFromCode = art_check_cast_from_code;
+
+  // Debug
+  points->pDebugMe = DebugMe;
+  points->pUpdateDebuggerFromCode = NULL; // Controlled by SetDebuggerUpdatesEnabled.
+
+  // DexCache
+  points->pInitializeStaticStorage = art_initialize_static_storage_from_code;
+  points->pInitializeTypeAndVerifyAccessFromCode = art_initialize_type_and_verify_access_from_code;
+  points->pInitializeTypeFromCode = art_initialize_type_from_code;
+  points->pResolveStringFromCode = art_resolve_string_from_code;
+
+  // Field
+  points->pSet32Instance = art_set32_instance_from_code;
+  points->pSet32Static = art_set32_static_from_code;
+  points->pSet64Instance = art_set64_instance_from_code;
+  points->pSet64Static = art_set64_static_from_code;
+  points->pSetObjInstance = art_set_obj_instance_from_code;
+  points->pSetObjStatic = art_set_obj_static_from_code;
+  points->pGet32Instance = art_get32_instance_from_code;
+  points->pGet64Instance = art_get64_instance_from_code;
+  points->pGetObjInstance = art_get_obj_instance_from_code;
+  points->pGet32Static = art_get32_static_from_code;
+  points->pGet64Static = art_get64_static_from_code;
+  points->pGetObjStatic = art_get_obj_static_from_code;
+
+  // FillArray
+  points->pHandleFillArrayDataFromCode = art_handle_fill_data_from_code;
+
+  // JNI
+  points->pDecodeJObjectInThread = DecodeJObjectInThread;
+  points->pFindNativeMethod = FindNativeMethod;
+
+  // Locks
+  points->pLockObjectFromCode = art_lock_object_from_code;
+  points->pUnlockObjectFromCode = art_unlock_object_from_code;
+
+  // Math
+  points->pCmpgDouble = CmpgDouble;
+  points->pCmpgFloat = CmpgFloat;
+  points->pCmplDouble = CmplDouble;
+  points->pCmplFloat = CmplFloat;
+  points->pDadd = __aeabi_dadd;
+  points->pDdiv = __aeabi_ddiv;
+  points->pDmul = __aeabi_dmul;
+  points->pDsub = __aeabi_dsub;
+  points->pF2d = __aeabi_f2d;
+  points->pFmod = fmod;
+  points->pI2d = __aeabi_i2d;
+  points->pL2d = __aeabi_l2d;
+  points->pD2f = __aeabi_d2f;
+  points->pFadd = __aeabi_fadd;
+  points->pFdiv = __aeabi_fdiv;
+  points->pFmodf = fmodf;
+  points->pFmul = __aeabi_fmul;
+  points->pFsub = __aeabi_fsub;
+  points->pI2f = __aeabi_i2f;
+  points->pL2f = __aeabi_l2f;
+  points->pD2iz = __aeabi_d2iz;
+  points->pF2iz = __aeabi_f2iz;
+  points->pIdiv = __aeabi_idivmod;
+  points->pIdivmod = __aeabi_idivmod;
+  points->pD2l = D2L;
+  points->pF2l = F2L;
+  points->pLadd = NULL;
+  points->pLand = NULL;
+  points->pLdivmod = __aeabi_ldivmod;
+  points->pLmul = __aeabi_lmul;
+  points->pLor = NULL;
+  points->pLsub = NULL;
+  points->pLxor = NULL;
+  points->pShlLong = art_shl_long;
+  points->pShrLong = art_shr_long;
+  points->pUshrLong = art_ushr_long;
+
+  // Intrinsics
+  points->pIndexOf = art_indexof;
+  points->pMemcmp16 = __memcmp16;
+  points->pStringCompareTo = art_string_compareto;
+  points->pMemcpy = memcpy;
+
+  // Invocation
+  points->pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
+  points->pInvokeDirectTrampolineWithAccessCheck = art_invoke_direct_trampoline_with_access_check;
+  points->pInvokeInterfaceTrampoline = art_invoke_interface_trampoline;
+  points->pInvokeInterfaceTrampolineWithAccessCheck = art_invoke_interface_trampoline_with_access_check;
+  points->pInvokeStaticTrampolineWithAccessCheck = art_invoke_static_trampoline_with_access_check;
+  points->pInvokeSuperTrampolineWithAccessCheck = art_invoke_super_trampoline_with_access_check;
+  points->pInvokeVirtualTrampolineWithAccessCheck = art_invoke_virtual_trampoline_with_access_check;
+
+  // Thread
+  points->pCheckSuspendFromCode = CheckSuspendFromCode;
+  points->pTestSuspendFromCode = art_test_suspend;
+
+  // Throws
+  points->pDeliverException = art_deliver_exception_from_code;
+  points->pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode;
+  points->pThrowArrayBoundsFromCode = art_throw_array_bounds_from_code;
+  points->pThrowDivZeroFromCode = art_throw_div_zero_from_code;
+  points->pThrowNoSuchMethodFromCode = art_throw_no_such_method_from_code;
+  points->pThrowNullPointerFromCode = art_throw_null_pointer_exception_from_code;
+  points->pThrowStackOverflowFromCode = art_throw_stack_overflow_from_code;
+  points->pThrowVerificationErrorFromCode = art_throw_verification_error_from_code;
+};
+
+void ChangeDebuggerEntryPoint(EntryPoints* points, bool enabled) {
+  points->pUpdateDebuggerFromCode = (enabled ? art_update_debugger : NULL);
+}
+
+bool IsTraceExitPc(uintptr_t pc) {
+  uintptr_t trace_exit = reinterpret_cast<uintptr_t>(art_trace_exit_from_code);
+  return pc == trace_exit;
+}
+
+void* GetLogTraceEntryPoint() {
+  return reinterpret_cast<void*>(art_trace_entry_from_code);
+}
+
+}  // namespace art
diff --git a/src/runtime_support_arm.S b/src/oat/runtime/arm/runtime_support_arm.S
similarity index 90%
rename from src/runtime_support_arm.S
rename to src/oat/runtime/arm/runtime_support_arm.S
index 653465a..5446919 100644
--- a/src/runtime_support_arm.S
+++ b/src/oat/runtime/arm/runtime_support_arm.S
@@ -1,17 +1,20 @@
 #include "asm_support.h"
 
-    .balign 4
-
     /* Deliver the given exception */
     .extern artDeliverExceptionFromCode
     /* Deliver an exception pending on a thread */
     .extern artDeliverPendingException
 
+    /* Cache alignment for function entry */
+.macro ALIGN_FUNCTION_ENTRY
+    .balign 16
+.endm
+
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveAll)
      */
-.macro SETUP_CALLEE_SAVE_FRAME
+.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     push {r4-r11, lr} @ 9 words of callee saves
     vpush {s0-s31}
     sub sp, #12       @ 3 words of space, bottom word will hold Method*
@@ -58,117 +61,81 @@
      * exception is Thread::Current()->exception_
      */
 .macro DELIVER_PENDING_EXCEPTION
-    SETUP_CALLEE_SAVE_FRAME                    @ save callee saves for throw
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME           @ save callee saves for throw
     mov    r0, r9                              @ pass Thread::Current
     mov    r1, sp                              @ pass SP
     b      artDeliverPendingExceptionFromCode  @ artDeliverPendingExceptionFromCode(Thread*, SP)
 .endm
 
-    .global art_update_debugger
-    .extern artUpdateDebuggerFromCode
-    /*
-     * On entry, r0 and r1 must be preserved, r2 is dex PC
-     */
-art_update_debugger:
-    mov    r3, r0         @ stash away r0 so that it's saved as if it were an argument
-    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
-    mov    r0, r2         @ arg0 is dex PC
-    mov    r1, rSELF      @ arg1 is Thread*
-    mov    r2, sp         @ arg2 is sp
-    bl     artUpdateDebuggerFromCode      @ artUpdateDebuggerFromCode(int32_t, Thread*, Method**)
-    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
-    mov    r0, r3         @ restore original r0
-    bx     lr
+.macro NO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
+    .global \c_name
+    .extern \cxx_name
+    ALIGN_FUNCTION_ENTRY
+\c_name:
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
+    mov r0, r9                      @ pass Thread::Current
+    mov r1, sp                      @ pass SP
+    b   \cxx_name                   @ \cxx_name(Thread*, SP)
+.endm
 
-    .global art_do_long_jump
-    /*
-     * On entry r0 is uint32_t* gprs_ and r1 is uint32_t* fprs_
-     */
-art_do_long_jump:
-    vldm r1, {s0-s31}     @ load all fprs from argument fprs_
-    ldr  r2, [r0, #60]    @ r2 = r15 (PC from gprs_ 60=4*15)
-    add  r0, r0, #12      @ increment r0 to skip gprs_[0..2] 12=4*3
-    ldm  r0, {r3-r14}     @ load remaining gprs from argument gprs_
-    mov  r0, #0           @ clear result registers r0 and r1
-    mov  r1, #0
-    bx   r2               @ do long jump
-
-    .global art_deliver_exception_from_code
-    /*
-     * Called by managed code, saves most registers (forms basis of long jump context) and passes
-     * the bottom of the stack. artDeliverExceptionFromCode will place the callee save Method* at
-     * the bottom of the thread. On entry r0 holds Throwable*
-     */
-art_deliver_exception_from_code:
-    SETUP_CALLEE_SAVE_FRAME
+.macro ONE_ARG_RUNTIME_EXCEPTION c_name, cxx_name
+    .global \c_name
+    .extern \cxx_name
+    ALIGN_FUNCTION_ENTRY
+\c_name:
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
     mov r1, r9                      @ pass Thread::Current
     mov r2, sp                      @ pass SP
-    b   artDeliverExceptionFromCode @ artDeliverExceptionFromCode(Throwable*, Thread*, SP)
+    b   \cxx_name                   @ \cxx_name(Thread*, SP)
+.endm
 
-    .global art_throw_null_pointer_exception_from_code
-    .extern artThrowNullPointerExceptionFromCode
-    /*
-     * Called by managed code to create and deliver a NullPointerException
-     */
-art_throw_null_pointer_exception_from_code:
-    SETUP_CALLEE_SAVE_FRAME
-    mov r0, r9                               @ pass Thread::Current
-    mov r1, sp                               @ pass SP
-    b   artThrowNullPointerExceptionFromCode @ artThrowNullPointerExceptionFromCode(Thread*, SP)
-
-    .global art_throw_div_zero_from_code
-    .extern artThrowDivZeroFromCode
-    /*
-     * Called by managed code to create and deliver an ArithmeticException
-     */
-art_throw_div_zero_from_code:
-    SETUP_CALLEE_SAVE_FRAME
-    mov r0, r9                  @ pass Thread::Current
-    mov r1, sp                  @ pass SP
-    b   artThrowDivZeroFromCode @ artThrowDivZeroFromCode(Thread*, SP)
-
-    .global art_throw_array_bounds_from_code
-    .extern artThrowArrayBoundsFromCode
-    /*
-     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException
-     */
-art_throw_array_bounds_from_code:
-    SETUP_CALLEE_SAVE_FRAME
+.macro TWO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
+    .global \c_name
+    .extern \cxx_name
+    ALIGN_FUNCTION_ENTRY
+\c_name:
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
     mov r2, r9                      @ pass Thread::Current
     mov r3, sp                      @ pass SP
-    b   artThrowArrayBoundsFromCode @ artThrowArrayBoundsFromCode(index, limit, Thread*, SP)
+    b   \cxx_name                   @ \cxx_name(Thread*, SP)
+.endm
 
-    .global art_throw_stack_overflow_from_code
-    .extern artThrowStackOverflowFromCode
-art_throw_stack_overflow_from_code:
-    SETUP_CALLEE_SAVE_FRAME
-    mov r1, r9                        @ pass Thread::Current
-    mov r2, sp                        @ pass SP
-    b   artThrowStackOverflowFromCode @ artThrowStackOverflowFromCode(method, Thread*, SP)
+    /*
+     * Called by managed code, saves callee saves and then calls artThrowException
+     * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
+     */
+ONE_ARG_RUNTIME_EXCEPTION art_deliver_exception_from_code, artDeliverExceptionFromCode
 
-    .global art_throw_neg_array_size_from_code
-    .extern artThrowNegArraySizeFromCode
-art_throw_neg_array_size_from_code:
-    SETUP_CALLEE_SAVE_FRAME
-    mov r1, r9                        @ pass Thread::Current
-    mov r2, sp                        @ pass SP
-    b   artThrowNegArraySizeFromCode  @ artThrowNegArraySizeFromCode(size, Thread*, SP)
+    /*
+     * Called by managed code to create and deliver a NullPointerException.
+     */
+NO_ARG_RUNTIME_EXCEPTION art_throw_null_pointer_exception_from_code, artThrowNullPointerExceptionFromCode
 
-    .global art_throw_no_such_method_from_code
-    .extern artThrowNoSuchMethodFromCode
-art_throw_no_such_method_from_code:
-    SETUP_CALLEE_SAVE_FRAME
-    mov r1, r9                        @ pass Thread::Current
-    mov r2, sp                        @ pass SP
-    b   artThrowNoSuchMethodFromCode  @ artThrowNoSuchMethodFromCode(method_idx, Thread*, SP)
+    /*
+     * Called by managed code to create and deliver an ArithmeticException.
+     */
+NO_ARG_RUNTIME_EXCEPTION art_throw_div_zero_from_code, artThrowDivZeroFromCode
 
-    .global art_throw_verification_error_from_code
-    .extern artThrowVerificationErrorFromCode
-art_throw_verification_error_from_code:
-    SETUP_CALLEE_SAVE_FRAME
-    mov r2, r9                            @ pass Thread::Current
-    mov r3, sp                            @ pass SP
-    b   artThrowVerificationErrorFromCode @ artThrowVerificationErrorFromCode(kind, ref, Thread*, SP)
+    /*
+     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
+     * index, arg2 holds limit.
+     */
+TWO_ARG_RUNTIME_EXCEPTION art_throw_array_bounds_from_code, artThrowArrayBoundsFromCode
+
+    /*
+     * Called by managed code to create and deliver a StackOverflowError.
+     */
+NO_ARG_RUNTIME_EXCEPTION art_throw_stack_overflow_from_code, artThrowStackOverflowFromCode
+
+    /*
+     * Called by managed code to create and deliver a NoSuchMethodError.
+     */
+ONE_ARG_RUNTIME_EXCEPTION art_throw_no_such_method_from_code, artThrowNoSuchMethodFromCode
+
+    /*
+     * Called by managed code to create and deliver verification errors. Arg1 is kind, arg2 is ref.
+     */
+TWO_ARG_RUNTIME_EXCEPTION art_throw_verification_error_from_code, artThrowVerificationErrorFromCode
 
     /*
      * All generated callsites for interface invokes and invocation slow paths will load arguments
@@ -189,6 +156,7 @@
 .macro INVOKE_TRAMPOLINE c_name, cxx_name
     .global \c_name
     .extern \cxx_name
+    ALIGN_FUNCTION_ENTRY
 \c_name:
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME  @ save callee saves in case allocation triggers GC
     ldr    r2, [sp, #48]                  @ pass caller Method*
@@ -210,11 +178,43 @@
 INVOKE_TRAMPOLINE art_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
 INVOKE_TRAMPOLINE art_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
 
+    .global art_update_debugger
+    .extern artUpdateDebuggerFromCode
+    /*
+     * On entry, r0 and r1 must be preserved, r2 is dex PC
+     */
+     ALIGN_FUNCTION_ENTRY
+art_update_debugger:
+    mov    r3, r0         @ stash away r0 so that it's saved as if it were an argument
+    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+    mov    r0, r2         @ arg0 is dex PC
+    mov    r1, rSELF      @ arg1 is Thread*
+    mov    r2, sp         @ arg2 is sp
+    bl     artUpdateDebuggerFromCode      @ artUpdateDebuggerFromCode(int32_t, Thread*, Method**)
+    RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
+    mov    r0, r3         @ restore original r0
+    bx     lr
+
+    .global art_do_long_jump
+    /*
+     * On entry r0 is uint32_t* gprs_ and r1 is uint32_t* fprs_
+     */
+     ALIGN_FUNCTION_ENTRY
+art_do_long_jump:
+    vldm r1, {s0-s31}     @ load all fprs from argument fprs_
+    ldr  r2, [r0, #60]    @ r2 = r15 (PC from gprs_ 60=4*15)
+    add  r0, r0, #12      @ increment r0 to skip gprs_[0..2] 12=4*3
+    ldm  r0, {r3-r14}     @ load remaining gprs from argument gprs_
+    mov  r0, #0           @ clear result registers r0 and r1
+    mov  r1, #0
+    bx   r2               @ do long jump
+
     .global art_work_around_app_jni_bugs
     .extern artWorkAroundAppJniBugs
     /*
      * Entry point of native methods when JNI bug compatibility is enabled.
      */
+    ALIGN_FUNCTION_ENTRY
 art_work_around_app_jni_bugs:
     @ save registers that may contain arguments and LR that will be crushed by a call
     push {r0-r3, lr}
@@ -233,6 +233,7 @@
      * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
      * failure.
      */
+    ALIGN_FUNCTION_ENTRY
 art_handle_fill_data_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case exception allocation triggers GC
     mov    r2, r9                          @ pass Thread::Current
@@ -246,8 +247,9 @@
     .global art_lock_object_from_code
     .extern artLockObjectFromCode
     /*
-     * Entry from managed code that calls artLockObjectFromCode, may block for GC
+     * Entry from managed code that calls artLockObjectFromCode, may block for GC.
      */
+    ALIGN_FUNCTION_ENTRY
 art_lock_object_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case we block
     mov    r1, r9                     @ pass Thread::Current
@@ -260,6 +262,7 @@
     /*
      * Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
      */
+    ALIGN_FUNCTION_ENTRY
 art_unlock_object_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case exception allocation triggers GC
     mov    r1, r9                   @ pass Thread::Current
@@ -275,6 +278,7 @@
     /*
      * Entry from managed code that calls artCheckCastFromCode and delivers exception on failure.
      */
+    ALIGN_FUNCTION_ENTRY
 art_check_cast_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME    @ save callee saves in case exception allocation triggers GC
     mov    r2, r9                       @ pass Thread::Current
@@ -291,6 +295,7 @@
      * Entry from managed code that calls artCanPutArrayElementFromCode and delivers exception on
      * failure.
      */
+    ALIGN_FUNCTION_ENTRY
 art_can_put_array_element_from_code:
     cmp    r0, #0                         @ return if element == NULL
     bxeq   lr
@@ -310,6 +315,7 @@
      * initializer and deliver the exception on error. On success the static storage base is
      * returned.
      */
+    ALIGN_FUNCTION_ENTRY
 art_initialize_static_storage_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME           @ save callee saves in case of GC
     mov    r2, r9                              @ pass Thread::Current
@@ -326,6 +332,7 @@
     /*
      * Entry from managed code when dex cache misses for a type_idx
      */
+    ALIGN_FUNCTION_ENTRY
 art_initialize_type_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME           @ save callee saves in case of GC
     mov    r2, r9                              @ pass Thread::Current
@@ -341,8 +348,9 @@
     .extern artInitializeTypeAndVerifyAccessFromCode
     /*
      * Entry from managed code when type_idx needs to be checked for access and dex cache may also
-     * miss
+     * miss.
      */
+    ALIGN_FUNCTION_ENTRY
 art_initialize_type_and_verify_access_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME           @ save callee saves in case of GC
     mov    r2, r9                              @ pass Thread::Current
@@ -357,8 +365,9 @@
     .global art_get32_static_from_code
     .extern artGet32StaticFromCode
     /*
-     * Called by managed code to resolve a static field and load a 32-bit primitive value
+     * Called by managed code to resolve a static field and load a 32-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get32_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r1, [sp, #32]                 @ pass referrer
@@ -374,8 +383,9 @@
     .global art_get64_static_from_code
     .extern artGet64StaticFromCode
     /*
-     * Called by managed code to resolve a static field and load a 64-bit primitive value
+     * Called by managed code to resolve a static field and load a 64-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get64_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r1, [sp, #32]                 @ pass referrer
@@ -391,8 +401,9 @@
     .global art_get_obj_static_from_code
     .extern artGetObjStaticFromCode
     /*
-     * Called by managed code to resolve a static field and load an object reference
+     * Called by managed code to resolve a static field and load an object reference.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get_obj_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r1, [sp, #32]                 @ pass referrer
@@ -408,8 +419,9 @@
     .global art_get32_instance_from_code
     .extern artGet32InstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and load a 32-bit primitive value
+     * Called by managed code to resolve an instance field and load a 32-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get32_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r2, [sp, #32]                 @ pass referrer
@@ -425,8 +437,9 @@
     .global art_get64_instance_from_code
     .extern artGet64InstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and load a 64-bit primitive value
+     * Called by managed code to resolve an instance field and load a 64-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get64_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r2, [sp, #32]                 @ pass referrer
@@ -442,8 +455,9 @@
     .global art_get_obj_instance_from_code
     .extern artGetObjInstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and load an object reference
+     * Called by managed code to resolve an instance field and load an object reference.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get_obj_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r2, [sp, #32]                 @ pass referrer
@@ -459,8 +473,9 @@
     .global art_set32_static_from_code
     .extern artSet32StaticFromCode
     /*
-     * Called by managed code to resolve a static field and store a 32-bit primitive value
+     * Called by managed code to resolve a static field and store a 32-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set32_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r2, [sp, #32]                 @ pass referrer
@@ -475,8 +490,9 @@
     .global art_set64_static_from_code
     .extern artSet32StaticFromCode
     /*
-     * Called by managed code to resolve a static field and store a 64-bit primitive value
+     * Called by managed code to resolve a static field and store a 64-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set64_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r1, [sp, #32]                 @ pass referrer
@@ -493,8 +509,9 @@
     .global art_set_obj_static_from_code
     .extern artSetObjStaticFromCode
     /*
-     * Called by managed code to resolve a static field and store an object reference
+     * Called by managed code to resolve a static field and store an object reference.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set_obj_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r2, [sp, #32]                 @ pass referrer
@@ -509,8 +526,9 @@
     .global art_set32_instance_from_code
     .extern artSet32InstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and store a 32-bit primitive value
+     * Called by managed code to resolve an instance field and store a 32-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set32_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r3, [sp, #32]                 @ pass referrer
@@ -527,8 +545,9 @@
     .global art_set64_instance_from_code
     .extern artSet32InstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and store a 64-bit primitive value
+     * Called by managed code to resolve an instance field and store a 64-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set64_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     mov    r12, sp                       @ save SP
@@ -544,8 +563,9 @@
     .global art_set_obj_instance_from_code
     .extern artSetObjInstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and store an object reference
+     * Called by managed code to resolve an instance field and store an object reference.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set_obj_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     ldr    r3, [sp, #32]                 @ pass referrer
@@ -567,6 +587,7 @@
      * R1 holds the string index. The fast path check for hit in strings cache has already been
      * performed.
      */
+    ALIGN_FUNCTION_ENTRY
 art_resolve_string_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     mov    r2, r9                     @ pass Thread::Current
@@ -583,6 +604,7 @@
     /*
      * Called by managed code to allocate an object
      */
+    ALIGN_FUNCTION_ENTRY
 art_alloc_object_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     mov    r2, r9                     @ pass Thread::Current
@@ -597,8 +619,9 @@
     .extern artAllocObjectFromCodeWithAccessCheck
     /*
      * Called by managed code to allocate an object when the caller doesn't know whether it has
-     * access to the created type
+     * access to the created type.
      */
+    ALIGN_FUNCTION_ENTRY
 art_alloc_object_from_code_with_access_check:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     mov    r2, r9                     @ pass Thread::Current
@@ -612,8 +635,9 @@
     .global art_alloc_array_from_code
     .extern artAllocArrayFromCode
     /*
-     * Called by managed code to allocate an array
+     * Called by managed code to allocate an array.
      */
+    ALIGN_FUNCTION_ENTRY
 art_alloc_array_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     mov    r3, r9                     @ pass Thread::Current
@@ -629,8 +653,9 @@
     .extern artAllocArrayFromCodeWithAccessCheck
     /*
      * Called by managed code to allocate an array when the caller doesn't know whether it has
-     * access to the created type
+     * access to the created type.
      */
+    ALIGN_FUNCTION_ENTRY
 art_alloc_array_from_code_with_access_check:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     mov    r3, r9                     @ pass Thread::Current
@@ -645,8 +670,9 @@
     .global art_check_and_alloc_array_from_code
     .extern artCheckAndAllocArrayFromCode
     /*
-     * Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY
+     * Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY.
      */
+    ALIGN_FUNCTION_ENTRY
 art_check_and_alloc_array_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     mov    r3, r9                     @ pass Thread::Current
@@ -661,8 +687,9 @@
     .global art_check_and_alloc_array_from_code_with_access_check
     .extern artCheckAndAllocArrayFromCodeWithAccessCheck
     /*
-     * Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY
+     * Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY.
      */
+    ALIGN_FUNCTION_ENTRY
 art_check_and_alloc_array_from_code_with_access_check:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     mov    r3, r9                     @ pass Thread::Current
@@ -677,8 +704,9 @@
     .global art_test_suspend
     .extern artTestSuspendFromCode
     /*
-     * Called by managed code when the value in rSUSPEND has been decremented to 0
+     * Called by managed code when the value in rSUSPEND has been decremented to 0.
      */
+    ALIGN_FUNCTION_ENTRY
 art_test_suspend:
     ldr    r0, [rSELF, #THREAD_SUSPEND_COUNT_OFFSET]
     mov    rSUSPEND, #SUSPEND_CHECK_INTERVAL  @ reset rSUSPEND to SUSPEND_CHECK_INTERVAL
@@ -694,8 +722,9 @@
     .extern artProxyInvokeHandler
     /*
      * Called by managed code that is attempting to call a method on a proxy class. On entry
-     * r0 holds the proxy method; r1, r2 and r3 may contain arguments
+     * r0 holds the proxy method; r1, r2 and r3 may contain arguments.
      */
+    ALIGN_FUNCTION_ENTRY
 art_proxy_invoke_handler:
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
     str     r0, [sp, #0]           @ place proxy method at bottom of frame
@@ -713,8 +742,9 @@
     .global art_trace_entry_from_code
     .extern artTraceMethodEntryFromCode
     /*
-     * Routine that intercepts method calls
+     * Routine that intercepts method calls.
      */
+    ALIGN_FUNCTION_ENTRY
 art_trace_entry_from_code:
     push  {r0-r3}        @ save arguments (4 words)
     mov   r1, r9         @ pass Thread::Current
@@ -728,8 +758,9 @@
     .global art_trace_exit_from_code
     .extern artTraceMethodExitFromCode
     /*
-     * Routine that intercepts method returns
+     * Routine that intercepts method returns.
      */
+    ALIGN_FUNCTION_ENTRY
 art_trace_exit_from_code:
     push  {r0-r1}        @ save return value
     blx   artTraceMethodExitFromCode  @ ()
@@ -738,7 +769,6 @@
     bx    lr             @ return
 
     .global art_shl_long
-art_shl_long:
     /*
      * Long integer shift.  This is different from the generic 32/64-bit
      * binary operations because vAA/vBB are 64-bit but vCC (the shift
@@ -750,6 +780,8 @@
      *   r2: shift count
      */
     /* shl-long vAA, vBB, vCC */
+    ALIGN_FUNCTION_ENTRY
+art_shl_long:
     and     r2, r2, #63                 @ r2<- r2 & 0x3f
     mov     r1, r1, asl r2              @  r1<- r1 << r2
     rsb     r3, r2, #32                 @  r3<- 32 - r2
@@ -759,9 +791,7 @@
     mov     r0, r0, asl r2              @  r0<- r0 << r2
     bx      lr
 
-    .balign 4
     .global art_shr_long
-art_shr_long:
     /*
      * Long integer shift.  This is different from the generic 32/64-bit
      * binary operations because vAA/vBB are 64-bit but vCC (the shift
@@ -773,6 +803,8 @@
      *   r2: shift count
      */
     /* shr-long vAA, vBB, vCC */
+    ALIGN_FUNCTION_ENTRY
+art_shr_long:
     and     r2, r2, #63                 @ r0<- r0 & 0x3f
     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
     rsb     r3, r2, #32                 @  r3<- 32 - r2
@@ -782,9 +814,7 @@
     mov     r1, r1, asr r2              @  r1<- r1 >> r2
     bx      lr
 
-    .balign 4
     .global art_ushr_long
-art_ushr_long:
     /*
      * Long integer shift.  This is different from the generic 32/64-bit
      * binary operations because vAA/vBB are 64-bit but vCC (the shift
@@ -796,6 +826,8 @@
      *   r2: shift count
      */
     /* ushr-long vAA, vBB, vCC */
+    ALIGN_FUNCTION_ENTRY
+art_ushr_long:
     and     r2, r2, #63                 @ r0<- r0 & 0x3f
     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
     rsb     r3, r2, #32                 @  r3<- 32 - r2
diff --git a/src/stub_arm.cc b/src/oat/runtime/arm/stub_arm.cc
similarity index 93%
rename from src/stub_arm.cc
rename to src/oat/runtime/arm/stub_arm.cc
index 29d6bb2..d6426e8 100644
--- a/src/stub_arm.cc
+++ b/src/oat/runtime/arm/stub_arm.cc
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#include "assembler_arm.h"
 #include "jni_internal.h"
+#include "oat/utils/arm/assembler_arm.h"
+#include "oat/runtime/oat_support_entrypoints.h"
 #include "object.h"
 #include "stack_indirect_reference_table.h"
 
@@ -42,7 +43,7 @@
   // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetCoreSpillMask());
   __ PushList(save);
   __ LoadFromOffset(kLoadWord, R12, TR,
-                    OFFSETOF_MEMBER(Thread, pUnresolvedDirectMethodTrampolineFromCode));
+                    ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
   __ mov(R2, ShifterOperand(TR));  // Pass Thread::Current() in R2
   __ LoadImmediate(R3, type);
   __ IncreaseFrameSize(8);         // 2 words of space for alignment
@@ -87,7 +88,7 @@
   __ mov(R1, ShifterOperand(R9));  // Pass Thread::Current() in R1
   __ mov(R2, ShifterOperand(SP));  // Pass SP in R2
   // Call to throw AbstractMethodError
-  __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pThrowAbstractMethodErrorFromCode));
+  __ LoadFromOffset(kLoadWord, R12, TR, ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode));
   __ mov(PC, ShifterOperand(R12));  // Leaf call to routine that never returns
 
   __ bkpt(0);
@@ -111,7 +112,7 @@
   __ AddConstant(SP, -12);         // Ensure 16-byte alignment
   __ mov(R0, ShifterOperand(R9));  // Pass Thread::Current() in R0
   // Call FindNativeMethod
-  __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pFindNativeMethod));
+  __ LoadFromOffset(kLoadWord, R12, TR, ENTRYPOINT_OFFSET(pFindNativeMethod));
   __ blx(R12);
   __ mov(R12, ShifterOperand(R0));  // Save result of FindNativeMethod in R12
   __ AddConstant(SP, 12);           // Restore registers (including outgoing arguments)
diff --git a/src/oat/runtime/callee_save_frame.h b/src/oat/runtime/callee_save_frame.h
new file mode 100644
index 0000000..96811ce
--- /dev/null
+++ b/src/oat/runtime/callee_save_frame.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 Google Inc. All Rights Reserved.
+ *
+ * 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_SRC_OAT_RUNTIME_CALLEE_SAVE_FRAME_H_
+#define ART_SRC_OAT_RUNTIME_CALLEE_SAVE_FRAME_H_
+
+#include "thread.h"
+
+namespace art {
+
+class Method;
+
+// Place a special frame at the TOS that will save the callee saves for the given type
+static void  FinishCalleeSaveFrameSetup(Thread* self, Method** sp, Runtime::CalleeSaveType type) {
+  // Be aware the store below may well stomp on an incoming argument
+  *sp = Runtime::Current()->GetCalleeSaveMethod(type);
+  self->SetTopOfStack(sp, 0);
+  self->VerifyStack();
+}
+
+}  // namespace art
+
+#endif  // ART_SRC_OAT_RUNTIME_CALLEE_SAVE_FRAME_H_
diff --git a/src/context.cc b/src/oat/runtime/context.cc
similarity index 92%
rename from src/context.cc
rename to src/oat/runtime/context.cc
index 330ed1e..998e762 100644
--- a/src/context.cc
+++ b/src/oat/runtime/context.cc
@@ -16,8 +16,8 @@
 
 #include "context.h"
 
-#include "context_arm.h"
-#include "context_x86.h"
+#include "arm/context_arm.h"
+#include "x86/context_x86.h"
 
 namespace art {
 
diff --git a/src/context.h b/src/oat/runtime/context.h
similarity index 95%
rename from src/context.h
rename to src/oat/runtime/context.h
index 82e8315..b8852d5 100644
--- a/src/context.h
+++ b/src/oat/runtime/context.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_CONTEXT_H_
-#define ART_SRC_CONTEXT_H_
+#ifndef ART_SRC_OAT_RUNTIME_CONTEXT_H_
+#define ART_SRC_OAT_RUNTIME_CONTEXT_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -99,4 +99,4 @@
 
 }  // namespace art
 
-#endif  // ART_SRC_CONTEXT_H_
+#endif  // ART_SRC_OAT_RUNTIME_CONTEXT_H_
diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
new file mode 100644
index 0000000..e20332a
--- /dev/null
+++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
@@ -0,0 +1,274 @@
+/*
+ * 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 "oat/runtime/oat_support_entrypoints.h"
+
+namespace art {
+
+// Alloc entrypoints.
+extern "C" void* art_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_alloc_object_from_code(uint32_t type_idx, void* method);
+extern "C" void* art_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
+extern "C" void* art_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+
+// Cast entrypoints.
+extern uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class);
+extern "C" void art_can_put_array_element_from_code(void*, void*);
+extern "C" void art_check_cast_from_code(void*, void*);
+
+// Debug entrypoints.
+extern void DebugMe(Method* method, uint32_t info);
+extern "C" void art_update_debugger(void*, void*, int32_t, void*);
+
+// DexCache entrypoints.
+extern "C" void* art_initialize_static_storage_from_code(uint32_t, void*);
+extern "C" void* art_initialize_type_from_code(uint32_t, void*);
+extern "C" void* art_initialize_type_and_verify_access_from_code(uint32_t, void*);
+extern "C" void* art_resolve_string_from_code(void*, uint32_t);
+
+// Field entrypoints.
+extern "C" int art_set32_instance_from_code(uint32_t, void*, int32_t);
+extern "C" int art_set32_static_from_code(uint32_t, int32_t);
+extern "C" int art_set64_instance_from_code(uint32_t, void*, int64_t);
+extern "C" int art_set64_static_from_code(uint32_t, int64_t);
+extern "C" int art_set_obj_instance_from_code(uint32_t, void*, void*);
+extern "C" int art_set_obj_static_from_code(uint32_t, void*);
+extern "C" int32_t art_get32_instance_from_code(uint32_t, void*);
+extern "C" int32_t art_get32_static_from_code(uint32_t);
+extern "C" int64_t art_get64_instance_from_code(uint32_t, void*);
+extern "C" int64_t art_get64_static_from_code(uint32_t);
+extern "C" void* art_get_obj_instance_from_code(uint32_t, void*);
+extern "C" void* art_get_obj_static_from_code(uint32_t);
+
+// FillArray entrypoint.
+extern "C" void art_handle_fill_data_from_code(void*, void*);
+
+// JNI entrypoints.
+extern Object* DecodeJObjectInThread(Thread* thread, jobject obj);
+extern void* FindNativeMethod(Thread* thread);
+
+// Lock entrypoints.
+extern "C" void art_lock_object_from_code(void*);
+extern "C" void art_unlock_object_from_code(void*);
+
+// Math entrypoints.
+extern int32_t CmpgDouble(double a, double b);
+extern int32_t CmplDouble(double a, double b);
+extern int32_t CmpgFloat(float a, float b);
+extern int32_t CmplFloat(float a, float b);
+
+// Math conversions.
+extern "C" float __floatsisf(int op1);        // INT_TO_FLOAT
+extern "C" int32_t __fixsfsi(float op1);      // FLOAT_TO_INT
+extern "C" float __truncdfsf2(double op1);    // DOUBLE_TO_FLOAT
+extern "C" double __extendsfdf2(float op1);   // FLOAT_TO_DOUBLE
+extern "C" double __floatsidf(int op1);       // INT_TO_DOUBLE
+extern "C" int32_t __fixdfsi(double op1);     // DOUBLE_TO_INT
+extern "C" float __floatdisf(int64_t op1);    // LONG_TO_FLOAT
+extern "C" double __floatdidf(int64_t op1);   // LONG_TO_DOUBLE
+extern "C" int64_t __fixsfdi(float op1);      // FLOAT_TO_LONG
+extern "C" int64_t __fixdfdi(double op1);     // DOUBLE_TO_LONG
+extern int64_t D2L(double d);
+extern int64_t F2L(float f);
+
+// Single-precision FP arithmetics.
+extern "C" float __addsf3(float a, float b);   // ADD_FLOAT[_2ADDR]
+extern "C" float __subsf3(float a, float b);   // SUB_FLOAT[_2ADDR]
+extern "C" float __divsf3(float a, float b);   // DIV_FLOAT[_2ADDR]
+extern "C" float __mulsf3(float a, float b);   // MUL_FLOAT[_2ADDR]
+extern "C" float fmodf(float a, float b);      // REM_FLOAT[_2ADDR]
+
+// Double-precision FP arithmetics.
+extern "C" double __adddf3(double a, double b); // ADD_DOUBLE[_2ADDR]
+extern "C" double __subdf3(double a, double b); // SUB_DOUBLE[_2ADDR]
+extern "C" double __divdf3(double a, double b); // DIV_DOUBLE[_2ADDR]
+extern "C" double __muldf3(double a, double b); // MUL_DOUBLE[_2ADDR]
+extern "C" double fmod(double a, double b);     // REM_DOUBLE[_2ADDR]
+
+// Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR]
+extern "C" long long __divdi3(int64_t op1, int64_t op2);
+extern "C" long long __moddi3(int64_t op1, int64_t op2);
+extern "C" uint64_t art_shl_long(uint64_t, uint32_t);
+extern "C" uint64_t art_shr_long(uint64_t, uint32_t);
+extern "C" uint64_t art_ushr_long(uint64_t, uint32_t);
+
+// Intrinsic entrypoints.
+extern "C" int32_t __memcmp16(void*, void*, int32_t);
+extern "C" int32_t art_indexof(void*, uint32_t, uint32_t, uint32_t);
+extern "C" int32_t art_string_compareto(void*, void*);
+
+// Invoke entrypoints.
+const void* UnresolvedDirectMethodTrampolineFromCode(Method*, Method**, Thread*,
+                                                     Runtime::TrampolineType);
+extern "C" void art_invoke_direct_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_interface_trampoline(uint32_t, void*);
+extern "C" void art_invoke_interface_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_static_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_super_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
+
+// Thread entrypoints.
+extern void CheckSuspendFromCode(Thread* thread);
+extern "C" void art_test_suspend();
+
+// Throw entrypoints.
+extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
+extern "C" void art_deliver_exception_from_code(void*);
+extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
+extern "C" void art_throw_div_zero_from_code();
+extern "C" void art_throw_no_such_method_from_code(int32_t method_idx);
+extern "C" void art_throw_null_pointer_exception_from_code();
+extern "C" void art_throw_stack_overflow_from_code(void*);
+extern "C" void art_throw_verification_error_from_code(int32_t src1, int32_t ref);
+
+// Trace entrypoints.
+extern "C" void art_trace_entry_from_code(void*);
+extern "C" void art_trace_exit_from_code();
+
+void InitEntryPoints(EntryPoints* points) {
+  // Alloc
+  points->pAllocArrayFromCode = art_alloc_array_from_code;
+  points->pAllocArrayFromCodeWithAccessCheck = art_alloc_array_from_code_with_access_check;
+  points->pAllocObjectFromCode = art_alloc_object_from_code;
+  points->pAllocObjectFromCodeWithAccessCheck = art_alloc_object_from_code_with_access_check;
+  points->pCheckAndAllocArrayFromCode = art_check_and_alloc_array_from_code;
+  points->pCheckAndAllocArrayFromCodeWithAccessCheck = art_check_and_alloc_array_from_code_with_access_check;
+
+  // Cast
+  points->pInstanceofNonTrivialFromCode = IsAssignableFromCode;
+  points->pCanPutArrayElementFromCode = art_can_put_array_element_from_code;
+  points->pCheckCastFromCode = art_check_cast_from_code;
+
+  // Debug
+  points->pDebugMe = DebugMe;
+  points->pUpdateDebuggerFromCode = NULL; // Controlled by SetDebuggerUpdatesEnabled.
+
+  // DexCache
+  points->pInitializeStaticStorage = art_initialize_static_storage_from_code;
+  points->pInitializeTypeAndVerifyAccessFromCode = art_initialize_type_and_verify_access_from_code;
+  points->pInitializeTypeFromCode = art_initialize_type_from_code;
+  points->pResolveStringFromCode = art_resolve_string_from_code;
+
+  // Field
+  points->pSet32Instance = art_set32_instance_from_code;
+  points->pSet32Static = art_set32_static_from_code;
+  points->pSet64Instance = art_set64_instance_from_code;
+  points->pSet64Static = art_set64_static_from_code;
+  points->pSetObjInstance = art_set_obj_instance_from_code;
+  points->pSetObjStatic = art_set_obj_static_from_code;
+  points->pGet32Instance = art_get32_instance_from_code;
+  points->pGet64Instance = art_get64_instance_from_code;
+  points->pGetObjInstance = art_get_obj_instance_from_code;
+  points->pGet32Static = art_get32_static_from_code;
+  points->pGet64Static = art_get64_static_from_code;
+  points->pGetObjStatic = art_get_obj_static_from_code;
+
+  // FillArray
+  points->pHandleFillArrayDataFromCode = art_handle_fill_data_from_code;
+
+  // JNI
+  points->pDecodeJObjectInThread = DecodeJObjectInThread;
+  points->pFindNativeMethod = FindNativeMethod;
+
+  // Locks
+  points->pLockObjectFromCode = art_lock_object_from_code;
+  points->pUnlockObjectFromCode = art_unlock_object_from_code;
+
+  // Math
+  points->pCmpgDouble = CmpgDouble;
+  points->pCmpgFloat = CmpgFloat;
+  points->pCmplDouble = CmplDouble;
+  points->pCmplFloat = CmplFloat;
+  points->pDadd = __adddf3;
+  points->pDdiv = __subdf3;
+  points->pDmul = __muldf3;
+  points->pDsub = __subdf3;
+  points->pF2d = __extendsfdf2;
+  points->pFmod = fmod;
+  points->pI2d = __floatsidf;
+  points->pL2d = __floatdidf;
+  points->pD2f = __truncdfsf2;
+  points->pFadd = __addsf3;
+  points->pFdiv = __divsf3;
+  points->pFmodf = fmodf;
+  points->pFmul = __mulsf3;
+  points->pFsub = __subsf3;
+  points->pI2f = __floatsisf;
+  points->pL2f = __floatdisf;
+  points->pD2iz = __fixdfsi;
+  points->pF2iz = __fixsfi;
+  points->pIdiv = NULL;
+  points->pIdivmod = NULL;
+  points->pD2l = D2L;
+  points->pF2l = F2L;
+  points->pLadd = NULL;
+  points->pLand = NULL;
+  points->pLdivmod = NULL;
+  points->pLmul = NULL;
+  points->pLor = NULL;
+  points->pLsub = NULL;
+  points->pLxor = NULL;
+  points->pShlLong = art_shl_long;
+  points->pShrLong = art_shr_long;
+  points->pUshrLong = art_ushr_long;
+
+  // Intrinsics
+  points->pIndexOf = art_indexof;
+  points->pMemcmp16 = __memcmp16;
+  points->pStringCompareTo = art_string_compareto;
+  points->pMemcpy = memcpy;
+
+  // Invocation
+  points->pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
+  points->pInvokeDirectTrampolineWithAccessCheck = art_invoke_direct_trampoline_with_access_check;
+  points->pInvokeInterfaceTrampoline = art_invoke_interface_trampoline;
+  points->pInvokeInterfaceTrampolineWithAccessCheck = art_invoke_interface_trampoline_with_access_check;
+  points->pInvokeStaticTrampolineWithAccessCheck = art_invoke_static_trampoline_with_access_check;
+  points->pInvokeSuperTrampolineWithAccessCheck = art_invoke_super_trampoline_with_access_check;
+  points->pInvokeVirtualTrampolineWithAccessCheck = art_invoke_virtual_trampoline_with_access_check;
+
+  // Thread
+  points->pCheckSuspendFromCode = CheckSuspendFromCode;
+  points->pTestSuspendFromCode = art_test_suspend;
+
+  // Throws
+  points->pDeliverException = art_deliver_exception_from_code;
+  points->pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode;
+  points->pThrowArrayBoundsFromCode = art_throw_array_bounds_from_code;
+  points->pThrowDivZeroFromCode = art_throw_div_zero_from_code;
+  points->pThrowNoSuchMethodFromCode = art_throw_no_such_method_from_code;
+  points->pThrowNullPointerFromCode = art_throw_null_pointer_exception_from_code;
+  points->pThrowStackOverflowFromCode = art_throw_stack_overflow_from_code;
+  points->pThrowVerificationErrorFromCode = art_throw_verification_error_from_code;
+};
+
+void ChangeDebuggerEntryPoint(EntryPoints* points, bool enabled) {
+  points->pUpdateDebuggerFromCode = (enabled ? art_update_debugger : NULL);
+}
+
+bool IsTraceExitPc(uintptr_t pc) {
+  UNIMPLEMENTED(FATAL);
+  return false;
+}
+
+void* GetLogTraceEntryPoint() {
+  UNIMPLEMENTED(FATAL);
+  return NULL;
+}
+
+}  // namespace art
diff --git a/src/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S
similarity index 90%
rename from src/runtime_support_mips.S
rename to src/oat/runtime/mips/runtime_support_mips.S
index 3323564..65431e3 100644
--- a/src/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -7,12 +7,17 @@
     /* Deliver an exception pending on a thread */
     .extern artDeliverPendingException
 
+    /* Cache alignment for function entry */
+.macro ALIGN_FUNCTION_ENTRY
+    .balign 16
+.endm
+
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveAll)
      * callee-save: s0-s8 + ra, 10 total + 2 words
      */
-.macro SETUP_CALLEE_SAVE_FRAME
+.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     addiu  sp, sp, 48
     sw     ra, 44(sp)
     sw     s8, 40(sp)
@@ -91,7 +96,7 @@
      * exception is Thread::Current()->exception_
      */
 .macro DELIVER_PENDING_EXCEPTION
-    SETUP_CALLEE_SAVE_FRAME                     @ save callee saves for throw
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME            @ save callee saves for throw
     move    a0, rSELF                           @ pass Thread::Current
     b       artDeliverPendingExceptionFromCode  @ artDeliverPendingExceptionFromCode(Thread*, SP)
     move    a1, sp                              @ pass SP
@@ -133,6 +138,7 @@
     /*
      * On entry, a0 and a1 must be preserved, a2 is dex PC
      */
+    ALIGN_FUNCTION_ENTRY
 art_update_debugger:
     move    a3, a0         @ stash away a0 so that it's saved as if it were an argument
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
@@ -149,6 +155,7 @@
      * On entry a0 is uint32_t* gprs_ and a1 is uint32_t* fprs_
      * FIXME: just guessing about the shape of the jmpbuf.  Where will pc be?
      */
+    ALIGN_FUNCTION_ENTRY
 art_do_long_jump:
     l.s     f0, 0(a1)
     l.s     f1, 4(a1)
@@ -223,8 +230,9 @@
      * the bottom of the stack. artDeliverExceptionFromCode will place the callee save Method* at
      * the bottom of the thread. On entry r0 holds Throwable*
      */
+    ALIGN_FUNCTION_ENTRY
 art_deliver_exception_from_code:
-    SETUP_CALLEE_SAVE_FRAME
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move a1, rSELF                      @ pass Thread::Current
     b    artDeliverExceptionFromCode    @ artDeliverExceptionFromCode(Throwable*, Thread*, SP)
     move a2, sp                         @ pass SP
@@ -234,8 +242,9 @@
     /*
      * Called by managed code to create and deliver a NullPointerException
      */
+    ALIGN_FUNCTION_ENTRY
 art_throw_null_pointer_exception_from_code:
-    SETUP_CALLEE_SAVE_FRAME
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move a0, rSELF                            @ pass Thread::Current
     b   artThrowNullPointerExceptionFromCode  @ artThrowNullPointerExceptionFromCode(Thread*, SP)
     move a1, sp                               @ pass SP
@@ -245,8 +254,9 @@
     /*
      * Called by managed code to create and deliver an ArithmeticException
      */
+    ALIGN_FUNCTION_ENTRY
 art_throw_div_zero_from_code:
-    SETUP_CALLEE_SAVE_FRAME
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move a0, rSELF                  @ pass Thread::Current
     b   artThrowDivZeroFromCode     @ artThrowDivZeroFromCode(Thread*, SP)
     move a1, sp                     @ pass SP
@@ -256,40 +266,57 @@
     /*
      * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException
      */
+    ALIGN_FUNCTION_ENTRY
 art_throw_array_bounds_from_code:
-    SETUP_CALLEE_SAVE_FRAME
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move a2, rSELF                   @ pass Thread::Current
     b   artThrowArrayBoundsFromCode  @ artThrowArrayBoundsFromCode(index, limit, Thread*, SP)
     move a3, sp                      @ pass SP
 
     .global art_throw_stack_overflow_from_code
     .extern artThrowStackOverflowFromCode
+    /*
+     * Called by managed code to create and deliver a StackOverflowError.
+     */
+    ALIGN_FUNCTION_ENTRY
 art_throw_stack_overflow_from_code:
-    SETUP_CALLEE_SAVE_FRAME
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move a1, rSELF                     @ pass Thread::Current
     b   artThrowStackOverflowFromCode  @ artThrowStackOverflowFromCode(method, Thread*, SP)
     move a2, sp                        @ pass SP
 
     .global art_throw_neg_array_size_from_code
     .extern artThrowNegArraySizeFromCode
+    /*
+     * Called by managed code to create and deliver a NegativeArraySizeException.
+     */
+    ALIGN_FUNCTION_ENTRY
 art_throw_neg_array_size_from_code:
-    SETUP_CALLEE_SAVE_FRAME
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move a1, rSELF                        @ pass Thread::Current
     b   artThrowNegArraySizeFromCode      @ artThrowNegArraySizeFromCode(size, Thread*, SP)
     move a2, sp                           @ pass SP
 
     .global art_throw_no_such_method_from_code
     .extern artThrowNoSuchMethodFromCode
+    /*
+     * Called by managed code to create and deliver a NoSuchMethodError.
+     */
+    ALIGN_FUNCTION_ENTRY
 art_throw_no_such_method_from_code:
-    SETUP_CALLEE_SAVE_FRAME
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move a1, rSELF                        @ pass Thread::Current
     b   artThrowNoSuchMethodFromCode      @ artThrowNoSuchMethodFromCode(method_idx, Thread*, SP)
     move a2, sp                           @ pass SP
 
     .global art_throw_verification_error_from_code
     .extern artThrowVerificationErrorFromCode
+    /*
+     * Called by managed code to create and deliver verification errors.
+     */
+    ALIGN_FUNCTION_ENTRY
 art_throw_verification_error_from_code:
-    SETUP_CALLEE_SAVE_FRAME
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
     move a2, rSELF                            @ pass Thread::Current
     b   artThrowVerificationErrorFromCode     @ artThrowVerificationErrorFromCode(kind, ref, Thread*, SP)
     move a3, sp                               @ pass SP
@@ -342,6 +369,7 @@
     /*
      * Entry point of native methods when JNI bug compatibility is enabled.
      */
+    ALIGN_FUNCTION_ENTRY
 art_work_around_app_jni_bugs:
     @ save registers that may contain arguments and LR that will be crushed by a call
     addiu    sp, sp, -32
@@ -368,6 +396,7 @@
      * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
      * failure.
      */
+    ALIGN_FUNCTION_ENTRY
 art_handle_fill_data_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case exception allocation triggers GC
     move    a2, rSELF                          @ pass Thread::Current
@@ -384,10 +413,11 @@
     .global art_lock_object_from_code
     .extern artLockObjectFromCode
     /*
-     * Entry from managed code that calls artLockObjectFromCode, may block for GC
+     * Entry from managed code that calls artLockObjectFromCode, may block for GC.
      */
+    ALIGN_FUNCTION_ENTRY
 art_lock_object_from_code:
-    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case we block
+    SETUP_REF_ONLY_CALLEE_SAVE_FRAME      @ save callee saves in case we block
     move    a1, rSELF                     @ pass Thread::Current
     jal     artLockObjectFromCode         @ (Object* obj, Thread*, SP)
     move    a2, sp                        @ pass SP
@@ -398,11 +428,12 @@
     /*
      * Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
      */
+    ALIGN_FUNCTION_ENTRY
 art_unlock_object_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case exception allocation triggers GC
-    move    a1, rSELF                   @ pass Thread::Current
-    jal     artUnlockObjectFromCode     @ (Object* obj, Thread*, SP)
-    move    a2, sp                      @ pass SP
+    move    a1, rSELF                 @ pass Thread::Current
+    jal     artUnlockObjectFromCode   @ (Object* obj, Thread*, SP)
+    move    a2, sp                    @ pass SP
     RETURN_IF_ZERO
 
     .global art_check_cast_from_code
@@ -410,11 +441,12 @@
     /*
      * Entry from managed code that calls artCheckCastFromCode and delivers exception on failure.
      */
+    ALIGN_FUNCTION_ENTRY
 art_check_cast_from_code:
-    SETUP_REF_ONLY_CALLEE_SAVE_FRAME    @ save callee saves in case exception allocation triggers GC
-    move    a2, rSELF                       @ pass Thread::Current
-    jal     artCheckCastFromCode            @ (Class* a, Class* b, Thread*, SP)
-    move    a3, sp                          @ pass SP
+    SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case exception allocation triggers GC
+    move    a2, rSELF                 @ pass Thread::Current
+    jal     artCheckCastFromCode      @ (Class* a, Class* b, Thread*, SP)
+    move    a3, sp                    @ pass SP
     RETURN_IF_ZERO
 
     .global art_can_put_array_element_from_code
@@ -423,8 +455,9 @@
      * Entry from managed code that calls artCanPutArrayElementFromCode and delivers exception on
      * failure.
      */
+    ALIGN_FUNCTION_ENTRY
 art_can_put_array_element_from_code:
-    bnez   a0, 1f                         @ return if element == NULL
+    bnez   a0, 1f                       @ return if element == NULL
     nop
     jr     ra
     nop
@@ -442,8 +475,9 @@
      * initializer and deliver the exception on error. On success the static storage base is
      * returned.
      */
+    ALIGN_FUNCTION_ENTRY
 art_initialize_static_storage_from_code:
-    SETUP_REF_ONLY_CALLEE_SAVE_FRAME           @ save callee saves in case of GC
+    SETUP_REF_ONLY_CALLEE_SAVE_FRAME            @ save callee saves in case of GC
     move    a2, rSELF                           @ pass Thread::Current
     @ artInitializeStaticStorageFromCode(uint32_t type_idx, Method* referrer, Thread*, SP)
     jal     artInitializeStaticStorageFromCode
@@ -453,8 +487,9 @@
     .global art_initialize_type_from_code
     .extern artInitializeTypeFromCode
     /*
-     * Entry from managed code when dex cache misses for a type_idx
+     * Entry from managed code when dex cache misses for a type_idx.
      */
+    ALIGN_FUNCTION_ENTRY
 art_initialize_type_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME           @ save callee saves in case of GC
     move    a2, rSELF                          @ pass Thread::Current
@@ -467,8 +502,9 @@
     .extern artInitializeTypeAndVerifyAccessFromCode
     /*
      * Entry from managed code when type_idx needs to be checked for access and dex cache may also
-     * miss
+     * miss.
      */
+    ALIGN_FUNCTION_ENTRY
 art_initialize_type_and_verify_access_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME           @ save callee saves in case of GC
     move    a2, rSELF                           @ pass Thread::Current
@@ -480,8 +516,9 @@
     .global art_get32_static_from_code
     .extern artGet32StaticFromCode
     /*
-     * Called by managed code to resolve a static field and load a 32-bit primitive value
+     * Called by managed code to resolve a static field and load a 32-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get32_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a1, 48(sp)                    @ pass referrer's Method*
@@ -493,8 +530,9 @@
     .global art_get64_static_from_code
     .extern artGet64StaticFromCode
     /*
-     * Called by managed code to resolve a static field and load a 64-bit primitive value
+     * Called by managed code to resolve a static field and load a 64-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get64_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a1, 48(sp)                    @ pass referrer's Method*
@@ -506,8 +544,9 @@
     .global art_get_obj_static_from_code
     .extern artGetObjStaticFromCode
     /*
-     * Called by managed code to resolve a static field and load an object reference
+     * Called by managed code to resolve a static field and load an object reference.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get_obj_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a1, 48(sp)                    @ pass referrer's Method*
@@ -519,8 +558,9 @@
     .global art_get32_instance_from_code
     .extern artGet32InstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and load a 32-bit primitive value
+     * Called by managed code to resolve an instance field and load a 32-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get32_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a2, 48(sp)                    @ pass referrer's Method*
@@ -532,8 +572,9 @@
     .global art_get64_instance_from_code
     .extern artGet64InstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and load a 64-bit primitive value
+     * Called by managed code to resolve an instance field and load a 64-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get64_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a2, 48(sp)                    @ pass referrer's Method*
@@ -545,8 +586,9 @@
     .global art_get_obj_instance_from_code
     .extern artGetObjInstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and load an object reference
+     * Called by managed code to resolve an instance field and load an object reference.
      */
+    ALIGN_FUNCTION_ENTRY
 art_get_obj_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a2, 48(sp)                    @ pass referrer's Method*
@@ -558,8 +600,9 @@
     .global art_set32_static_from_code
     .extern artSet32StaticFromCode
     /*
-     * Called by managed code to resolve a static field and store a 32-bit primitive value
+     * Called by managed code to resolve a static field and store a 32-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set32_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a2, 48(sp)                    @ pass referrer's Method*
@@ -571,9 +614,9 @@
     .global art_set64_static_from_code
     .extern artSet32StaticFromCode
     /*
-     * Called by managed code to resolve a static field and store a 64-bit primitive value
+     * Called by managed code to resolve a static field and store a 64-bit primitive value.
      */
-
+    ALIGN_FUNCTION_ENTRY
 art_set64_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a1, 48(sp)                    @ pass referrer's Method*
@@ -588,8 +631,9 @@
     .global art_set_obj_static_from_code
     .extern artSetObjStaticFromCode
     /*
-     * Called by managed code to resolve a static field and store an object reference
+     * Called by managed code to resolve a static field and store an object reference.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set_obj_static_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a2, 48(sp)                    @ pass referrer's Method*
@@ -601,8 +645,9 @@
     .global art_set32_instance_from_code
     .extern artSet32InstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and store a 32-bit primitive value
+     * Called by managed code to resolve an instance field and store a 32-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set32_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a4, 48(sp)                    @ pass referrer's Method*
@@ -617,8 +662,9 @@
     .global art_set64_instance_from_code
     .extern artSet32InstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and store a 64-bit primitive value
+     * Called by managed code to resolve an instance field and store a 64-bit primitive value.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set64_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     move   t0, sp                        @ save SP
@@ -632,8 +678,9 @@
     .global art_set_obj_instance_from_code
     .extern artSetObjInstanceFromCode
     /*
-     * Called by managed code to resolve an instance field and store an object reference
+     * Called by managed code to resolve an instance field and store an object reference.
      */
+    ALIGN_FUNCTION_ENTRY
 art_set_obj_instance_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME     @ save callee saves in case of GC
     lw     a3, 48(sp)                    @ pass referrer's Method*
@@ -653,6 +700,7 @@
      * R1 holds the string index. The fast path check for hit in strings cache has already been
      * performed.
      */
+    ALIGN_FUNCTION_ENTRY
 art_resolve_string_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     move    a2, rSELF                 @ pass Thread::Current
@@ -664,8 +712,9 @@
     .global art_alloc_object_from_code
     .extern artAllocObjectFromCode
     /*
-     * Called by managed code to allocate an object
+     * Called by managed code to allocate an object.
      */
+    ALIGN_FUNCTION_ENTRY
 art_alloc_object_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     move    a2, rSELF                 @ pass Thread::Current
@@ -677,8 +726,9 @@
     .extern artAllocObjectFromCodeWithAccessCheck
     /*
      * Called by managed code to allocate an object when the caller doesn't know whether it has
-     * access to the created type
+     * access to the created type.
      */
+    ALIGN_FUNCTION_ENTRY
 art_alloc_object_from_code_with_access_check:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     move    a2, rSELF                 @ pass Thread::Current
@@ -689,8 +739,9 @@
     .global art_alloc_array_from_code
     .extern artAllocArrayFromCode
     /*
-     * Called by managed code to allocate an array
+     * Called by managed code to allocate an array.
      */
+    ALIGN_FUNCTION_ENTRY
 art_alloc_array_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     move    a3, r9                    @ pass Thread::Current
@@ -703,8 +754,9 @@
     .extern artAllocArrayFromCodeWithAccessCheck
     /*
      * Called by managed code to allocate an array when the caller doesn't know whether it has
-     * access to the created type
+     * access to the created type.
      */
+    ALIGN_FUNCTION_ENTRY
 art_alloc_array_from_code_with_access_check:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     move    a3, rSELF                 @ pass Thread::Current
@@ -716,8 +768,9 @@
     .global art_check_and_alloc_array_from_code
     .extern artCheckAndAllocArrayFromCode
     /*
-     * Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY
+     * Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY.
      */
+    ALIGN_FUNCTION_ENTRY
 art_check_and_alloc_array_from_code:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     move    a3, rSELF                 @ pass Thread::Current
@@ -729,8 +782,9 @@
     .global art_check_and_alloc_array_from_code_with_access_check
     .extern artCheckAndAllocArrayFromCodeWithAccessCheck
     /*
-     * Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY
+     * Called by managed code to allocate an array in a special case for FILLED_NEW_ARRAY.
      */
+    ALIGN_FUNCTION_ENTRY
 art_check_and_alloc_array_from_code_with_access_check:
     SETUP_REF_ONLY_CALLEE_SAVE_FRAME  @ save callee saves in case of GC
     move   a3, rSELF                  @ pass Thread::Current
@@ -742,8 +796,9 @@
     .global art_test_suspend
     .extern artTestSuspendFromCode
     /*
-     * Called by managed code when the value in rSUSPEND has been decremented to 0
+     * Called by managed code when the value in rSUSPEND has been decremented to 0.
      */
+    ALIGN_FUNCTION_ENTRY
 art_test_suspend:
     lw     a0, THREAD_SUSPEND_COUNT_OFFSET(rSELF)
     bnez   a0, 1f
@@ -761,8 +816,9 @@
     .extern artProxyInvokeHandler
     /*
      * Called by managed code that is attempting to call a method on a proxy class. On entry
-     * r0 holds the proxy method; r1, r2 and r3 may contain arguments
+     * r0 holds the proxy method; r1, r2 and r3 may contain arguments.
      */
+    ALIGN_FUNCTION_ENTRY
 art_proxy_invoke_handler:
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
     sw      a0, 0(sp)             @ place proxy method at bottom of frame
@@ -775,7 +831,7 @@
     lw      v0, 12(sp)
     lw      v1, 14(sp)
     bnez    r0, 1f
-    addui   sp, sp, 48             @ pop frame
+    addui   sp, sp, 48            @ pop frame
     jr      ra
     nop
 1:
@@ -786,6 +842,7 @@
     /*
      * Routine that intercepts method calls
      */
+    ALIGN_FUNCTION_ENTRY
 art_trace_entry_from_code:
     addui    sp, sp, -16
     sw       a0, 0(sp)
@@ -809,6 +866,7 @@
     /*
      * Routine that intercepts method returns
      */
+    ALIGN_FUNCTION_ENTRY
 art_trace_exit_from_code:
     addui    sp, sp, -16
     sw       v0, 0(sp)
@@ -821,7 +879,6 @@
     addui    sp, sp, 16
 
     .global art_shl_long
-art_shl_long:
     /*
      * Long integer shift.  This is different from the generic 32/64-bit
      * binary operations because vAA/vBB are 64-bit but vCC (the shift
@@ -832,6 +889,8 @@
      *   a1: high word
      *   a2: shift count
      */
+    ALIGN_FUNCTION_ENTRY
+art_shl_long:
     /* shl-long vAA, vBB, vCC */
     sll     v0, a0, a2                     @  rlo<- alo << (shift&31)
     not     v1, a2                         @  rhi<- 31-shift  (shift is 5b)
@@ -844,9 +903,7 @@
     jr      ra
     movn    v0, zero, a2                   @  rlo<- 0  (if shift&0x20)
 
-    .balign 4
     .global art_shr_long
-art_shr_long:
     /*
      * Long integer shift.  This is different from the generic 32/64-bit
      * binary operations because vAA/vBB are 64-bit but vCC (the shift
@@ -857,6 +914,8 @@
      *   a1: high word
      *   a2: shift count
      */
+    ALIGN_FUNCTION_ENTRY
+art_shr_long:
     sra     v1, a1, a2                     @  rhi<- ahi >> (shift&31)
     srl     v0, a0, a2                     @  rlo<- alo >> (shift&31)
     sra     a3, a1, 31                     @  a3<- sign(ah)
@@ -869,9 +928,7 @@
     jr      ra
     movn    v1, a3, a2                     @  rhi<- sign(ahi) (if shift&0x20)
 
-    .balign 4
     .global art_ushr_long
-art_ushr_long:
     /*
      * Long integer shift.  This is different from the generic 32/64-bit
      * binary operations because vAA/vBB are 64-bit but vCC (the shift
@@ -883,6 +940,8 @@
      *   r2: shift count
      */
     /* ushr-long vAA, vBB, vCC */
+    ALIGN_FUNCTION_ENTRY
+art_ushr_long:
     sra     v1, a1, a2                     @  rhi<- ahi >> (shift&31)
     srl     v0, a0, a2                     @  rlo<- alo >> (shift&31)
     sra     a3, a1, 31                     @  a3<- sign(ah)
diff --git a/src/oat/runtime/oat_support_entrypoints.h b/src/oat/runtime/oat_support_entrypoints.h
new file mode 100644
index 0000000..0e59dd8
--- /dev/null
+++ b/src/oat/runtime/oat_support_entrypoints.h
@@ -0,0 +1,165 @@
+/*
+ * 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_SRC_OAT_RUNTIME_OAT_SUPPORT_ENTRYPOINTS_H_
+#define ART_SRC_OAT_RUNTIME_OAT_SUPPORT_ENTRYPOINTS_H_
+
+#include "runtime.h"
+
+#define ENTRYPOINT_OFFSET(x) \
+  (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, entrypoints_)) + \
+   static_cast<uintptr_t>(OFFSETOF_MEMBER(EntryPoints, x)))
+
+namespace art {
+
+class Class;
+class Method;
+class Thread;
+
+struct PACKED EntryPoints {
+  // Alloc
+  void* (*pAllocArrayFromCode)(uint32_t, void*, int32_t);
+  void* (*pAllocArrayFromCodeWithAccessCheck)(uint32_t, void*, int32_t);
+  void* (*pAllocObjectFromCode)(uint32_t, void*);
+  void* (*pAllocObjectFromCodeWithAccessCheck)(uint32_t, void*);
+  void* (*pCheckAndAllocArrayFromCode)(uint32_t, void*, int32_t);
+  void* (*pCheckAndAllocArrayFromCodeWithAccessCheck)(uint32_t, void*, int32_t);
+
+  // Cast
+  uint32_t (*pInstanceofNonTrivialFromCode)(const Class*, const Class*);
+  void (*pCanPutArrayElementFromCode)(void*, void*);
+  void (*pCheckCastFromCode)(void*, void*);
+
+  // Debug
+  void (*pDebugMe)(Method*, uint32_t);
+  void (*pUpdateDebuggerFromCode)(void*, void*, int32_t, void*);
+
+  // DexCache
+  void* (*pInitializeStaticStorage)(uint32_t, void*);
+  void* (*pInitializeTypeAndVerifyAccessFromCode)(uint32_t, void*);
+  void* (*pInitializeTypeFromCode)(uint32_t, void*);
+  void* (*pResolveStringFromCode)(void*, uint32_t);
+
+  // Field
+  int (*pSet32Instance)(uint32_t, void*, int32_t);  // field_idx, obj, src
+  int (*pSet32Static)(uint32_t, int32_t);
+  int (*pSet64Instance)(uint32_t, void*, int64_t);
+  int (*pSet64Static)(uint32_t, int64_t);
+  int (*pSetObjInstance)(uint32_t, void*, void*);
+  int (*pSetObjStatic)(uint32_t, void*);
+  int32_t (*pGet32Instance)(uint32_t, void*);
+  int32_t (*pGet32Static)(uint32_t);
+  int64_t (*pGet64Instance)(uint32_t, void*);
+  int64_t (*pGet64Static)(uint32_t);
+  void* (*pGetObjInstance)(uint32_t, void*);
+  void* (*pGetObjStatic)(uint32_t);
+
+  // FillArray
+  void (*pHandleFillArrayDataFromCode)(void*, void*);
+
+  // JNI
+  Object* (*pDecodeJObjectInThread)(Thread* thread, jobject obj);
+  void* (*pFindNativeMethod)(Thread* thread);
+
+  // Locks
+  void (*pLockObjectFromCode)(void*);
+  void (*pUnlockObjectFromCode)(void*);
+
+  // Math
+  int32_t (*pCmpgDouble)(double, double);
+  int32_t (*pCmpgFloat)(float, float);
+  int32_t (*pCmplDouble)(double, double);
+  int32_t (*pCmplFloat)(float, float);
+  double (*pDadd)(double, double);
+  double (*pDdiv)(double, double);
+  double (*pDmul)(double, double);
+  double (*pDsub)(double, double);
+  double (*pF2d)(float);
+  double (*pFmod)(double, double);
+  double (*pI2d)(int);
+  double (*pL2d)(int64_t);
+  float (*pD2f)(double);
+  float (*pFadd)(float, float);
+  float (*pFdiv)(float, float);
+  float (*pFmodf)(float, float);
+  float (*pFmul)(float, float);
+  float (*pFsub)(float, float);
+  float (*pI2f)(int32_t);
+  float (*pL2f)(int64_t);
+  int32_t (*pD2iz)(double);
+  int32_t (*pF2iz)(float);
+  int32_t (*pIdiv)(int32_t, int32_t);
+  int32_t (*pIdivmod)(int32_t, int32_t);
+  int64_t (*pD2l)(double);
+  int64_t (*pF2l)(float);
+  int64_t (*pLadd)(int64_t, int64_t);
+  int64_t (*pLand)(int64_t, int64_t);
+  int64_t (*pLdivmod)(int64_t, int64_t);
+  int64_t (*pLmul)(int64_t, int64_t);
+  int64_t (*pLor)(int64_t, int64_t);
+  int64_t (*pLsub)(int64_t, int64_t);
+  int64_t (*pLxor)(int64_t, int64_t);
+  uint64_t (*pShlLong)(uint64_t, uint32_t);
+  uint64_t (*pShrLong)(uint64_t, uint32_t);
+  uint64_t (*pUshrLong)(uint64_t, uint32_t);
+
+  // Intrinsics
+  int32_t (*pIndexOf)(void*, uint32_t, uint32_t, uint32_t);
+  int32_t (*pMemcmp16)(void*, void*, int32_t);
+  int32_t (*pStringCompareTo)(void*, void*);
+  void* (*pMemcpy)(void*, const void*, size_t);
+
+  // Invocation
+  Method* (*pFindInterfaceMethodInCache)(Class*, uint32_t, const Method*, struct DvmDex*);
+  const void* (*pUnresolvedDirectMethodTrampolineFromCode)(Method*, Method**, Thread*,
+                                                           Runtime::TrampolineType);
+  void (*pInvokeDirectTrampolineWithAccessCheck)(uint32_t, void*);
+  void (*pInvokeInterfaceTrampoline)(uint32_t, void*);
+  void (*pInvokeInterfaceTrampolineWithAccessCheck)(uint32_t, void*);
+  void (*pInvokeStaticTrampolineWithAccessCheck)(uint32_t, void*);
+  void (*pInvokeSuperTrampolineWithAccessCheck)(uint32_t, void*);
+  void (*pInvokeVirtualTrampolineWithAccessCheck)(uint32_t, void*);
+
+  // Thread
+  void (*pCheckSuspendFromCode)(Thread*);  // Stub that is called when the suspend count is non-zero
+  void (*pTestSuspendFromCode)();  // Stub that is periodically called to test the suspend count
+
+  // Throws
+  void (*pDeliverException)(void*);
+  void (*pThrowAbstractMethodErrorFromCode)(Method* m, Thread* thread, Method** sp);
+  void (*pThrowArrayBoundsFromCode)(int32_t, int32_t);
+  void (*pThrowDivZeroFromCode)();
+  void (*pThrowNoSuchMethodFromCode)(int32_t);
+  void (*pThrowNullPointerFromCode)();
+  void (*pThrowStackOverflowFromCode)(void*);
+  void (*pThrowVerificationErrorFromCode)(int32_t, int32_t);
+};
+
+// Initialize an entry point data structure.
+void InitEntryPoints(EntryPoints* points);
+
+// Change the debugger entry point in the data structure.
+void ChangeDebuggerEntryPoint(EntryPoints* points, bool enabled);
+
+// Is the given return_pc the trace exit return pc?
+bool IsTraceExitPc(uintptr_t pc);
+
+// Return address of stub that logs method entries.
+void* GetLogTraceEntryPoint();
+
+}  // namespace art
+
+#endif  // ART_SRC_OAT_RUNTIME_OAT_SUPPORT_ENTRYPOINTS_H_
diff --git a/src/oat/runtime/support_alloc.cc b/src/oat/runtime/support_alloc.cc
new file mode 100644
index 0000000..d9394d2
--- /dev/null
+++ b/src/oat/runtime/support_alloc.cc
@@ -0,0 +1,60 @@
+/*
+ * 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 "callee_save_frame.h"
+#include "runtime_support.h"
+
+namespace art {
+
+extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method,
+                                          Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return AllocObjectFromCode(type_idx, method, self, false);
+}
+
+extern "C" Object* artAllocObjectFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
+                                                         Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return AllocObjectFromCode(type_idx, method, self, true);
+}
+
+extern "C" Array* artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
+                                        Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return AllocArrayFromCode(type_idx, method, component_count, self, false);
+}
+
+extern "C" Array* artAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
+                                                       int32_t component_count,
+                                                       Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return AllocArrayFromCode(type_idx, method, component_count, self, true);
+}
+
+extern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method,
+                                               int32_t component_count, Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return CheckAndAllocArrayFromCode(type_idx, method, component_count, self, false);
+}
+
+extern "C" Array* artCheckAndAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
+                                                               int32_t component_count,
+                                                               Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return CheckAndAllocArrayFromCode(type_idx, method, component_count, self, true);
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_cast.cc b/src/oat/runtime/support_cast.cc
new file mode 100644
index 0000000..987e764
--- /dev/null
+++ b/src/oat/runtime/support_cast.cc
@@ -0,0 +1,65 @@
+/*
+ * 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 "callee_save_frame.h"
+#include "runtime_support.h"
+
+namespace art {
+
+// Assignable test for code, won't throw.  Null and equality tests already performed
+uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class) {
+  DCHECK(klass != NULL);
+  DCHECK(ref_class != NULL);
+  return klass->IsAssignableFrom(ref_class) ? 1 : 0;
+}
+
+// Check whether it is safe to cast one class to the other, throw exception and return -1 on failure
+extern "C" int artCheckCastFromCode(const Class* a, const Class* b, Thread* self, Method** sp) {
+  DCHECK(a->IsClass()) << PrettyClass(a);
+  DCHECK(b->IsClass()) << PrettyClass(b);
+  if (LIKELY(b->IsAssignableFrom(a))) {
+    return 0;  // Success
+  } else {
+    FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
+        "%s cannot be cast to %s",
+        PrettyDescriptor(a).c_str(),
+        PrettyDescriptor(b).c_str());
+    return -1;  // Failure
+  }
+}
+
+// Tests whether 'element' can be assigned into an array of type 'array_class'.
+// Returns 0 on success and -1 if an exception is pending.
+extern "C" int artCanPutArrayElementFromCode(const Object* element, const Class* array_class,
+                                             Thread* self, Method** sp) {
+  DCHECK(array_class != NULL);
+  // element can't be NULL as we catch this is screened in runtime_support
+  Class* element_class = element->GetClass();
+  Class* component_type = array_class->GetComponentType();
+  if (LIKELY(component_type->IsAssignableFrom(element_class))) {
+    return 0;  // Success
+  } else {
+    FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
+        "%s cannot be stored in an array of type %s",
+        PrettyDescriptor(element_class).c_str(),
+        PrettyDescriptor(array_class).c_str());
+    return -1;  // Failure
+  }
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_debug.cc b/src/oat/runtime/support_debug.cc
new file mode 100644
index 0000000..2803e27
--- /dev/null
+++ b/src/oat/runtime/support_debug.cc
@@ -0,0 +1,42 @@
+/*
+ * 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 "callee_save_frame.h"
+#include "debugger.h"
+
+namespace art {
+
+/*
+ * Report location to debugger.  Note: dex_pc is the current offset within
+ * the method.  However, because the offset alone cannot distinguish between
+ * method entry and offset 0 within the method, we'll use an offset of -1
+ * to denote method entry.
+ */
+extern "C" void artUpdateDebuggerFromCode(int32_t dex_pc, Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp,  Runtime::kRefsAndArgs);
+  Dbg::UpdateDebugger(dex_pc, self, sp);
+}
+
+// Temporary debugging hook for compiler.
+extern void DebugMe(Method* method, uint32_t info) {
+  LOG(INFO) << "DebugMe";
+  if (method != NULL) {
+    LOG(INFO) << PrettyMethod(method);
+  }
+  LOG(INFO) << "Info: " << info;
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_dexcache.cc b/src/oat/runtime/support_dexcache.cc
new file mode 100644
index 0000000..e5f2f82
--- /dev/null
+++ b/src/oat/runtime/support_dexcache.cc
@@ -0,0 +1,50 @@
+/*
+ * 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 "callee_save_frame.h"
+#include "runtime_support.h"
+
+namespace art {
+
+extern "C" Class* artInitializeStaticStorageFromCode(uint32_t type_idx, const Method* referrer,
+                                                     Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return ResolveVerifyAndClinit(type_idx, referrer, self, true, true);
+}
+
+extern "C" Class* artInitializeTypeFromCode(uint32_t type_idx, const Method* referrer, Thread* self,
+                                            Method** sp) {
+  // Called when method->dex_cache_resolved_types_[] misses
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return ResolveVerifyAndClinit(type_idx, referrer, self, false, false);
+}
+
+extern "C" Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx,
+                                                           const Method* referrer, Thread* self,
+                                                           Method** sp) {
+  // Called when caller isn't guaranteed to have access to a type and the dex cache may be
+  // unpopulated
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return ResolveVerifyAndClinit(type_idx, referrer, self, false, true);
+}
+
+extern "C" String* artResolveStringFromCode(Method* referrer, int32_t string_idx,
+                                            Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  return ResolveStringFromCode(referrer, string_idx);
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_field.cc b/src/oat/runtime/support_field.cc
new file mode 100644
index 0000000..77fe618
--- /dev/null
+++ b/src/oat/runtime/support_field.cc
@@ -0,0 +1,233 @@
+/*
+ * 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 "callee_save_frame.h"
+#include "runtime_support.h"
+
+#include <stdint.h>
+
+namespace art {
+
+extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const Method* referrer,
+                                           Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int32_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get32(NULL);
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, true, true, false, sizeof(int32_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get32(NULL);
+  }
+  return 0;  // Will throw exception by checking with Thread::Current
+}
+
+extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const Method* referrer,
+                                           Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int64_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get64(NULL);
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, true, true, false, sizeof(int64_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get64(NULL);
+  }
+  return 0;  // Will throw exception by checking with Thread::Current
+}
+
+extern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
+                                           Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(NULL);
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, true, false, false, sizeof(Object*));
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(NULL);
+  }
+  return NULL;  // Will throw exception by checking with Thread::Current
+}
+
+extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, Object* obj,
+                                             const Method* referrer, Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int32_t));
+  if (LIKELY(field != NULL && obj != NULL)) {
+    return field->Get32(obj);
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, false, true, false, sizeof(int32_t));
+  if (LIKELY(field != NULL)) {
+    if (UNLIKELY(obj == NULL)) {
+      ThrowNullPointerExceptionForFieldAccess(self, field, true);
+    } else {
+      return field->Get32(obj);
+    }
+  }
+  return 0;  // Will throw exception by checking with Thread::Current
+}
+
+extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, Object* obj,
+                                             const Method* referrer, Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int64_t));
+  if (LIKELY(field != NULL && obj != NULL)) {
+    return field->Get64(obj);
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, false, true, false, sizeof(int64_t));
+  if (LIKELY(field != NULL)) {
+    if (UNLIKELY(obj == NULL)) {
+      ThrowNullPointerExceptionForFieldAccess(self, field, true);
+    } else {
+      return field->Get64(obj);
+    }
+  }
+  return 0;  // Will throw exception by checking with Thread::Current
+}
+
+extern "C" Object* artGetObjInstanceFromCode(uint32_t field_idx, Object* obj,
+                                              const Method* referrer, Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
+  if (LIKELY(field != NULL && obj != NULL)) {
+    return field->GetObj(obj);
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, false, false, false, sizeof(Object*));
+  if (LIKELY(field != NULL)) {
+    if (UNLIKELY(obj == NULL)) {
+      ThrowNullPointerExceptionForFieldAccess(self, field, true);
+    } else {
+      return field->GetObj(obj);
+    }
+  }
+  return NULL;  // Will throw exception by checking with Thread::Current
+}
+
+extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
+                                      const Method* referrer, Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int32_t));
+  if (LIKELY(field != NULL)) {
+    field->Set32(NULL, new_value);
+    return 0;  // success
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, true, true, true, sizeof(int32_t));
+  if (LIKELY(field != NULL)) {
+    field->Set32(NULL, new_value);
+    return 0;  // success
+  }
+  return -1;  // failure
+}
+
+extern "C" int artSet64StaticFromCode(uint32_t field_idx, const Method* referrer,
+                                      uint64_t new_value, Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int64_t));
+  if (LIKELY(field != NULL)) {
+    field->Set64(NULL, new_value);
+    return 0;  // success
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, true, true, true, sizeof(int64_t));
+  if (LIKELY(field != NULL)) {
+    field->Set64(NULL, new_value);
+    return 0;  // success
+  }
+  return -1;  // failure
+}
+
+extern "C" int artSetObjStaticFromCode(uint32_t field_idx, Object* new_value,
+                                       const Method* referrer, Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
+  if (LIKELY(field != NULL)) {
+    if (LIKELY(!FieldHelper(field).IsPrimitiveType())) {
+      field->SetObj(NULL, new_value);
+      return 0;  // success
+    }
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, true, false, true, sizeof(Object*));
+  if (LIKELY(field != NULL)) {
+    field->SetObj(NULL, new_value);
+    return 0;  // success
+  }
+  return -1;  // failure
+}
+
+extern "C" int artSet32InstanceFromCode(uint32_t field_idx, Object* obj, uint32_t new_value,
+                                        const Method* referrer, Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int32_t));
+  if (LIKELY(field != NULL && obj != NULL)) {
+    field->Set32(obj, new_value);
+    return 0;  // success
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, false, true, true, sizeof(int32_t));
+  if (LIKELY(field != NULL)) {
+    if (UNLIKELY(obj == NULL)) {
+      ThrowNullPointerExceptionForFieldAccess(self, field, false);
+    } else {
+      field->Set32(obj, new_value);
+      return 0;  // success
+    }
+  }
+  return -1;  // failure
+}
+
+extern "C" int artSet64InstanceFromCode(uint32_t field_idx, Object* obj, uint64_t new_value,
+                                        Thread* self, Method** sp) {
+  Method* callee_save = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsOnly);
+  Method* referrer = sp[callee_save->GetFrameSizeInBytes() / sizeof(Method*)];
+  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int64_t));
+  if (LIKELY(field != NULL  && obj != NULL)) {
+    field->Set64(obj, new_value);
+    return 0;  // success
+  }
+  *sp = callee_save;
+  self->SetTopOfStack(sp, 0);
+  field = FindFieldFromCode(field_idx, referrer, self, false, true, true, sizeof(int64_t));
+  if (LIKELY(field != NULL)) {
+    if (UNLIKELY(obj == NULL)) {
+      ThrowNullPointerExceptionForFieldAccess(self, field, false);
+    } else {
+      field->Set64(obj, new_value);
+      return 0;  // success
+    }
+  }
+  return -1;  // failure
+}
+
+extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, Object* obj, Object* new_value,
+                                         const Method* referrer, Thread* self, Method** sp) {
+  Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
+  if (LIKELY(field != NULL && obj != NULL)) {
+    field->SetObj(obj, new_value);
+    return 0;  // success
+  }
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  field = FindFieldFromCode(field_idx, referrer, self, false, false, true, sizeof(Object*));
+  if (LIKELY(field != NULL)) {
+    if (UNLIKELY(obj == NULL)) {
+      ThrowNullPointerExceptionForFieldAccess(self, field, false);
+    } else {
+      field->SetObj(obj, new_value);
+      return 0;  // success
+    }
+  }
+  return -1;  // failure
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_fillarray.cc b/src/oat/runtime/support_fillarray.cc
new file mode 100644
index 0000000..eb1c46c
--- /dev/null
+++ b/src/oat/runtime/support_fillarray.cc
@@ -0,0 +1,59 @@
+/*
+ * 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 "callee_save_frame.h"
+#include "object.h"
+
+namespace art {
+
+/*
+ * Fill the array with predefined constant values, throwing exceptions if the array is null or
+ * not of sufficient length.
+ *
+ * NOTE: When dealing with a raw dex file, the data to be copied uses
+ * little-endian ordering.  Require that oat2dex do any required swapping
+ * so this routine can get by with a memcpy().
+ *
+ * Format of the data:
+ *  ushort ident = 0x0300   magic value
+ *  ushort width            width of each element in the table
+ *  uint   size             number of elements in the table
+ *  ubyte  data[size*width] table of data values (may contain a single-byte
+ *                          padding at the end)
+ */
+extern "C" int artHandleFillArrayDataFromCode(Array* array, const uint16_t* table,
+                                              Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  DCHECK_EQ(table[0], 0x0300);
+  if (UNLIKELY(array == NULL)) {
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
+        "null array in fill array");
+    return -1;  // Error
+  }
+  DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
+  uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16);
+  if (UNLIKELY(static_cast<int32_t>(size) > array->GetLength())) {
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
+        "failed array fill. length=%d; index=%d", array->GetLength(), size);
+    return -1;  // Error
+  }
+  uint16_t width = table[1];
+  uint32_t size_in_bytes = size * width;
+  memcpy((char*)array + Array::DataOffset(width).Int32Value(), (char*)&table[4], size_in_bytes);
+  return 0;  // Success
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_invoke.cc b/src/oat/runtime/support_invoke.cc
new file mode 100644
index 0000000..14040ce
--- /dev/null
+++ b/src/oat/runtime/support_invoke.cc
@@ -0,0 +1,92 @@
+/*
+ * 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 "callee_save_frame.h"
+#include "runtime_support.h"
+
+namespace art {
+
+static uint64_t artInvokeCommon(uint32_t method_idx, Object* this_object, Method* caller_method,
+                                Thread* self, Method** sp, bool access_check, InvokeType type){
+  Method* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
+  if (UNLIKELY(method == NULL)) {
+    FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
+    if (UNLIKELY(this_object == NULL && type != kDirect && type != kStatic)) {
+      ThrowNullPointerExceptionForMethodAccess(self, caller_method, method_idx, type);
+      return 0;  // failure
+    }
+    method = FindMethodFromCode(method_idx, this_object, caller_method, self, access_check, type);
+    if (UNLIKELY(method == NULL)) {
+      CHECK(self->IsExceptionPending());
+      return 0;  // failure
+    }
+  }
+  DCHECK(!self->IsExceptionPending());
+  const void* code = method->GetCode();
+
+  // When we return, the caller will branch to this address, so it had better not be 0!
+  CHECK(code != NULL) << PrettyMethod(method);
+
+  uint32_t method_uint = reinterpret_cast<uint32_t>(method);
+  uint64_t code_uint = reinterpret_cast<uint32_t>(code);
+  uint64_t result = ((code_uint << 32) | method_uint);
+  return result;
+}
+
+// See comments in runtime_support_asm.S
+extern "C" uint64_t artInvokeInterfaceTrampoline(uint32_t method_idx, Object* this_object,
+                                                 Method* caller_method, Thread* self,
+                                                 Method** sp) {
+  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, false, kInterface);
+}
+
+extern "C" uint64_t artInvokeInterfaceTrampolineWithAccessCheck(uint32_t method_idx,
+                                                                Object* this_object,
+                                                                Method* caller_method, Thread* self,
+                                                                Method** sp) {
+  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kInterface);
+}
+
+
+extern "C" uint64_t artInvokeDirectTrampolineWithAccessCheck(uint32_t method_idx,
+                                                             Object* this_object,
+                                                             Method* caller_method, Thread* self,
+                                                             Method** sp) {
+  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kDirect);
+}
+
+extern "C" uint64_t artInvokeStaticTrampolineWithAccessCheck(uint32_t method_idx,
+                                                            Object* this_object,
+                                                            Method* caller_method, Thread* self,
+                                                            Method** sp) {
+  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kStatic);
+}
+
+extern "C" uint64_t artInvokeSuperTrampolineWithAccessCheck(uint32_t method_idx,
+                                                            Object* this_object,
+                                                            Method* caller_method, Thread* self,
+                                                            Method** sp) {
+  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kSuper);
+}
+
+extern "C" uint64_t artInvokeVirtualTrampolineWithAccessCheck(uint32_t method_idx,
+                                                              Object* this_object,
+                                                              Method* caller_method, Thread* self,
+                                                              Method** sp) {
+  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kVirtual);
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_jni.cc b/src/oat/runtime/support_jni.cc
new file mode 100644
index 0000000..d74f78f
--- /dev/null
+++ b/src/oat/runtime/support_jni.cc
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2012 Google Inc. All Rights Reserved.
+ *
+ * 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 "object.h"
+#include "object_utils.h"
+#include "thread.h"
+
+namespace art {
+
+// Used by the JNI dlsym stub to find the native method to invoke if none is registered.
+extern void* FindNativeMethod(Thread* self) {
+  DCHECK(Thread::Current() == self);
+
+  Method* method = const_cast<Method*>(self->GetCurrentMethod());
+  DCHECK(method != NULL);
+
+  // Lookup symbol address for method, on failure we'll return NULL with an
+  // exception set, otherwise we return the address of the method we found.
+  void* native_code = self->GetJniEnv()->vm->FindCodeForNativeMethod(method);
+  if (native_code == NULL) {
+    DCHECK(self->IsExceptionPending());
+    return NULL;
+  } else {
+    // Register so that future calls don't come here
+    method->RegisterNative(self, native_code);
+    return native_code;
+  }
+}
+
+// Return value helper for jobject return types, used for JNI return values.
+extern Object* DecodeJObjectInThread(Thread* thread, jobject obj) {
+  if (thread->IsExceptionPending()) {
+    return NULL;
+  }
+  return thread->DecodeJObject(obj);
+}
+
+static void WorkAroundJniBugsForJobject(intptr_t* arg_ptr) {
+  intptr_t value = *arg_ptr;
+  Object** value_as_jni_rep = reinterpret_cast<Object**>(value);
+  Object* value_as_work_around_rep = value_as_jni_rep != NULL ? *value_as_jni_rep : NULL;
+  CHECK(Runtime::Current()->GetHeap()->IsHeapAddress(value_as_work_around_rep)) << value_as_work_around_rep;
+  *arg_ptr = reinterpret_cast<intptr_t>(value_as_work_around_rep);
+}
+
+extern "C" const void* artWorkAroundAppJniBugs(Thread* self, intptr_t* sp) {
+  DCHECK(Thread::Current() == self);
+  // TODO: this code is specific to ARM
+  // On entry the stack pointed by sp is:
+  // | arg3   | <- Calling JNI method's frame (and extra bit for out args)
+  // | LR     |
+  // | R3     |    arg2
+  // | R2     |    arg1
+  // | R1     |    jclass/jobject
+  // | R0     |    JNIEnv
+  // | unused |
+  // | unused |
+  // | unused | <- sp
+  Method* jni_method = self->GetTopOfStack().GetMethod();
+  DCHECK(jni_method->IsNative()) << PrettyMethod(jni_method);
+  intptr_t* arg_ptr = sp + 4;  // pointer to r1 on stack
+  // Fix up this/jclass argument
+  WorkAroundJniBugsForJobject(arg_ptr);
+  arg_ptr++;
+  // Fix up jobject arguments
+  MethodHelper mh(jni_method);
+  int reg_num = 2;  // Current register being processed, -1 for stack arguments.
+  for (uint32_t i = 1; i < mh.GetShortyLength(); i++) {
+    char shorty_char = mh.GetShorty()[i];
+    if (shorty_char == 'L') {
+      WorkAroundJniBugsForJobject(arg_ptr);
+    }
+    if (shorty_char == 'J' || shorty_char == 'D') {
+      if (reg_num == 2) {
+        arg_ptr = sp + 8;  // skip to out arguments
+        reg_num = -1;
+      } else if (reg_num == 3) {
+        arg_ptr = sp + 10;  // skip to out arguments plus 2 slots as long must be aligned
+        reg_num = -1;
+      } else {
+        DCHECK(reg_num == -1);
+        if ((reinterpret_cast<intptr_t>(arg_ptr) & 7) == 4) {
+          arg_ptr += 3;  // unaligned, pad and move through stack arguments
+        } else {
+          arg_ptr += 2;  // aligned, move through stack arguments
+        }
+      }
+    } else {
+      if (reg_num == 2) {
+        arg_ptr++; // move through register arguments
+        reg_num++;
+      } else if (reg_num == 3) {
+        arg_ptr = sp + 8;  // skip to outgoing stack arguments
+        reg_num = -1;
+      } else {
+        DCHECK(reg_num == -1);
+        arg_ptr++;  // move through stack arguments
+      }
+    }
+  }
+  // Load expected destination, see Method::RegisterNative
+  const void* code = reinterpret_cast<const void*>(jni_method->GetGcMapRaw());
+  if (UNLIKELY(code == NULL)) {
+    code = Runtime::Current()->GetJniDlsymLookupStub()->GetData();
+    jni_method->RegisterNative(self, code);
+  }
+  return code;
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_locks.cc b/src/oat/runtime/support_locks.cc
new file mode 100644
index 0000000..30fc567
--- /dev/null
+++ b/src/oat/runtime/support_locks.cc
@@ -0,0 +1,38 @@
+/*
+ * 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 "callee_save_frame.h"
+#include "object.h"
+
+namespace art {
+
+extern "C" int artUnlockObjectFromCode(Object* obj, Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+  DCHECK(obj != NULL);  // Assumed to have been checked before entry
+  // MonitorExit may throw exception
+  return obj->MonitorExit(self) ? 0 /* Success */ : -1 /* Failure */;
+}
+
+extern "C" void artLockObjectFromCode(Object* obj, Thread* thread, Method** sp) {
+  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly);
+  DCHECK(obj != NULL);        // Assumed to have been checked before entry
+  obj->MonitorEnter(thread);  // May block
+  DCHECK(thread->HoldsLock(obj));
+  // Only possible exception is NPE and is handled before entry
+  DCHECK(!thread->IsExceptionPending());
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_math.cc b/src/oat/runtime/support_math.cc
new file mode 100644
index 0000000..cb5f705
--- /dev/null
+++ b/src/oat/runtime/support_math.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012 Google Inc. All Rights Reserved.
+ *
+ * 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 <stdint.h>
+
+namespace art {
+
+int CmplFloat(float a, float b) {
+  if (a == b) {
+    return 0;
+  } else if (a < b) {
+    return -1;
+  } else if (a > b) {
+    return 1;
+  }
+  return -1;
+}
+
+int CmpgFloat(float a, float b) {
+  if (a == b) {
+    return 0;
+  } else if (a < b) {
+    return -1;
+  } else if (a > b) {
+    return 1;
+  }
+  return 1;
+}
+
+int CmpgDouble(double a, double b) {
+  if (a == b) {
+    return 0;
+  } else if (a < b) {
+    return -1;
+  } else if (a > b) {
+    return 1;
+  }
+  return 1;
+}
+
+int CmplDouble(double a, double b) {
+  if (a == b) {
+    return 0;
+  } else if (a < b) {
+    return -1;
+  } else if (a > b) {
+    return 1;
+  }
+  return -1;
+}
+
+/*
+ * Float/double conversion requires clamping to min and max of integer form.  If
+ * target doesn't support this normally, use these.
+ */
+int64_t D2L(double d) {
+  static const double kMaxLong = (double) (int64_t) 0x7fffffffffffffffULL;
+  static const double kMinLong = (double) (int64_t) 0x8000000000000000ULL;
+  if (d >= kMaxLong) {
+    return (int64_t) 0x7fffffffffffffffULL;
+  } else if (d <= kMinLong) {
+    return (int64_t) 0x8000000000000000ULL;
+  } else if (d != d)  { // NaN case
+    return 0;
+  } else {
+    return (int64_t) d;
+  }
+}
+
+int64_t F2L(float f) {
+  static const float kMaxLong = (float) (int64_t) 0x7fffffffffffffffULL;
+  static const float kMinLong = (float) (int64_t) 0x8000000000000000ULL;
+  if (f >= kMaxLong) {
+    return (int64_t) 0x7fffffffffffffffULL;
+  } else if (f <= kMinLong) {
+    return (int64_t) 0x8000000000000000ULL;
+  } else if (f != f) { // NaN case
+    return 0;
+  } else {
+    return (int64_t) f;
+  }
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_proxy.cc b/src/oat/runtime/support_proxy.cc
new file mode 100644
index 0000000..a9c7ebe
--- /dev/null
+++ b/src/oat/runtime/support_proxy.cc
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2012 Google Inc. All Rights Reserved.
+ *
+ * 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 "object.h"
+#include "object_utils.h"
+#include "reflection.h"
+#include "thread.h"
+
+#include "ScopedLocalRef.h"
+
+namespace art {
+
+static void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception) {
+  ScopedLocalRef<jclass> jlr_UTE_class(env,
+      env->FindClass("java/lang/reflect/UndeclaredThrowableException"));
+  if (jlr_UTE_class.get() == NULL) {
+    LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
+  } else {
+    jmethodID jlre_UTE_constructor = env->GetMethodID(jlr_UTE_class.get(), "<init>",
+                                                      "(Ljava/lang/Throwable;)V");
+    jthrowable jexception = AddLocalReference<jthrowable>(env, exception);
+    ScopedLocalRef<jthrowable> jlr_UTE(env,
+        reinterpret_cast<jthrowable>(env->NewObject(jlr_UTE_class.get(), jlre_UTE_constructor,
+                                                    jexception)));
+    int rc = env->Throw(jlr_UTE.get());
+    if (rc != JNI_OK) {
+      LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
+    }
+  }
+  CHECK(self->IsExceptionPending());
+}
+
+// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
+// which is responsible for recording callee save registers. We explicitly handlerize incoming
+// reference arguments (so they survive GC) and create a boxed argument array. Finally we invoke
+// the invocation handler which is a field within the proxy object receiver.
+extern "C" void artProxyInvokeHandler(Method* proxy_method, Object* receiver,
+                                      Thread* self, byte* stack_args) {
+  // Register the top of the managed stack
+  Method** proxy_sp = reinterpret_cast<Method**>(stack_args - 12);
+  DCHECK_EQ(*proxy_sp, proxy_method);
+  self->SetTopOfStack(proxy_sp, 0);
+  // TODO: ARM specific
+  DCHECK_EQ(proxy_method->GetFrameSizeInBytes(), 48u);
+  // Start new JNI local reference state
+  JNIEnvExt* env = self->GetJniEnv();
+  ScopedJniEnvLocalRefState env_state(env);
+  // Create local ref. copies of proxy method and the receiver
+  jobject rcvr_jobj = AddLocalReference<jobject>(env, receiver);
+  jobject proxy_method_jobj = AddLocalReference<jobject>(env, proxy_method);
+
+  // Placing into local references incoming arguments from the caller's register arguments,
+  // replacing original Object* with jobject
+  MethodHelper proxy_mh(proxy_method);
+  const size_t num_params = proxy_mh.NumArgs();
+  size_t args_in_regs = 0;
+  for (size_t i = 1; i < num_params; i++) {  // skip receiver
+    args_in_regs = args_in_regs + (proxy_mh.IsParamALongOrDouble(i) ? 2 : 1);
+    if (args_in_regs > 2) {
+      args_in_regs = 2;
+      break;
+    }
+  }
+  size_t cur_arg = 0;  // current stack location to read
+  size_t param_index = 1;  // skip receiver
+  while (cur_arg < args_in_regs && param_index < num_params) {
+    if (proxy_mh.IsParamAReference(param_index)) {
+      Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize));
+      jobject jobj = AddLocalReference<jobject>(env, obj);
+      *reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj;
+    }
+    cur_arg = cur_arg + (proxy_mh.IsParamALongOrDouble(param_index) ? 2 : 1);
+    param_index++;
+  }
+  // Placing into local references incoming arguments from the caller's stack arguments
+  cur_arg += 11;  // skip callee saves, LR, Method* and out arg spills for R1 to R3
+  while (param_index < num_params) {
+    if (proxy_mh.IsParamAReference(param_index)) {
+      Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize));
+      jobject jobj = AddLocalReference<jobject>(env, obj);
+      *reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj;
+    }
+    cur_arg = cur_arg + (proxy_mh.IsParamALongOrDouble(param_index) ? 2 : 1);
+    param_index++;
+  }
+  // Set up arguments array and place in local IRT during boxing (which may allocate/GC)
+  jvalue args_jobj[3];
+  args_jobj[0].l = rcvr_jobj;
+  args_jobj[1].l = proxy_method_jobj;
+  // Args array, if no arguments then NULL (don't include receiver in argument count)
+  args_jobj[2].l = NULL;
+  ObjectArray<Object>* args = NULL;
+  if ((num_params - 1) > 0) {
+    args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(num_params - 1);
+    if (args == NULL) {
+      CHECK(self->IsExceptionPending());
+      return;
+    }
+    args_jobj[2].l = AddLocalReference<jobjectArray>(env, args);
+  }
+  // Convert proxy method into expected interface method
+  Method* interface_method = proxy_method->FindOverriddenMethod();
+  DCHECK(interface_method != NULL);
+  DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
+  args_jobj[1].l = AddLocalReference<jobject>(env, interface_method);
+  // Box arguments
+  cur_arg = 0;  // reset stack location to read to start
+  // reset index, will index into param type array which doesn't include the receiver
+  param_index = 0;
+  ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes();
+  if (param_types == NULL) {
+    CHECK(self->IsExceptionPending());
+    return;
+  }
+  // Check number of parameter types agrees with number from the Method - less 1 for the receiver.
+  DCHECK_EQ(static_cast<size_t>(param_types->GetLength()), num_params - 1);
+  while (cur_arg < args_in_regs && param_index < (num_params - 1)) {
+    Class* param_type = param_types->Get(param_index);
+    Object* obj;
+    if (!param_type->IsPrimitive()) {
+      obj = self->DecodeJObject(*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)));
+    } else {
+      JValue val = *reinterpret_cast<JValue*>(stack_args + (cur_arg * kPointerSize));
+      if (cur_arg == 1 && (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble())) {
+        // long/double split over regs and stack, mask in high half from stack arguments
+        uint64_t high_half = *reinterpret_cast<uint32_t*>(stack_args + (13 * kPointerSize));
+        val.j = (val.j & 0xffffffffULL) | (high_half << 32);
+      }
+      BoxPrimitive(param_type->GetPrimitiveType(), val);
+      if (self->IsExceptionPending()) {
+        return;
+      }
+      obj = val.l;
+    }
+    args->Set(param_index, obj);
+    cur_arg = cur_arg + (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble() ? 2 : 1);
+    param_index++;
+  }
+  // Placing into local references incoming arguments from the caller's stack arguments
+  cur_arg += 11;  // skip callee saves, LR, Method* and out arg spills for R1 to R3
+  while (param_index < (num_params - 1)) {
+    Class* param_type = param_types->Get(param_index);
+    Object* obj;
+    if (!param_type->IsPrimitive()) {
+      obj = self->DecodeJObject(*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)));
+    } else {
+      JValue val = *reinterpret_cast<JValue*>(stack_args + (cur_arg * kPointerSize));
+      BoxPrimitive(param_type->GetPrimitiveType(), val);
+      if (self->IsExceptionPending()) {
+        return;
+      }
+      obj = val.l;
+    }
+    args->Set(param_index, obj);
+    cur_arg = cur_arg + (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble() ? 2 : 1);
+    param_index++;
+  }
+  // Get the InvocationHandler method and the field that holds it within the Proxy object
+  static jmethodID inv_hand_invoke_mid = NULL;
+  static jfieldID proxy_inv_hand_fid = NULL;
+  if (proxy_inv_hand_fid == NULL) {
+    ScopedLocalRef<jclass> proxy(env, env->FindClass("java/lang/reflect/Proxy"));
+    proxy_inv_hand_fid = env->GetFieldID(proxy.get(), "h", "Ljava/lang/reflect/InvocationHandler;");
+    ScopedLocalRef<jclass> inv_hand_class(env, env->FindClass("java/lang/reflect/InvocationHandler"));
+    inv_hand_invoke_mid = env->GetMethodID(inv_hand_class.get(), "invoke",
+        "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
+  }
+  DCHECK(env->IsInstanceOf(rcvr_jobj, env->FindClass("java/lang/reflect/Proxy")));
+  jobject inv_hand = env->GetObjectField(rcvr_jobj, proxy_inv_hand_fid);
+  // Call InvocationHandler.invoke
+  jobject result = env->CallObjectMethodA(inv_hand, inv_hand_invoke_mid, args_jobj);
+  // Place result in stack args
+  if (!self->IsExceptionPending()) {
+    Object* result_ref = self->DecodeJObject(result);
+    if (result_ref != NULL) {
+      JValue result_unboxed;
+      bool unboxed_okay = UnboxPrimitive(result_ref, proxy_mh.GetReturnType(), result_unboxed, "result");
+      if (!unboxed_okay) {
+        self->ClearException();
+        self->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
+                                 "Couldn't convert result of type %s to %s",
+                                 PrettyTypeOf(result_ref).c_str(),
+                                 PrettyDescriptor(proxy_mh.GetReturnType()).c_str());
+        return;
+      }
+      *reinterpret_cast<JValue*>(stack_args) = result_unboxed;
+    } else {
+      *reinterpret_cast<jobject*>(stack_args) = NULL;
+    }
+  } else {
+    // In the case of checked exceptions that aren't declared, the exception must be wrapped by
+    // a UndeclaredThrowableException.
+    Throwable* exception = self->GetException();
+    self->ClearException();
+    if (!exception->IsCheckedException()) {
+      self->SetException(exception);
+    } else {
+      SynthesizedProxyClass* proxy_class =
+          down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass());
+      int throws_index = -1;
+      size_t num_virt_methods = proxy_class->NumVirtualMethods();
+      for (size_t i = 0; i < num_virt_methods; i++) {
+        if (proxy_class->GetVirtualMethod(i) == proxy_method) {
+          throws_index = i;
+          break;
+        }
+      }
+      CHECK_NE(throws_index, -1);
+      ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
+      Class* exception_class = exception->GetClass();
+      bool declares_exception = false;
+      for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
+        Class* declared_exception = declared_exceptions->Get(i);
+        declares_exception = declared_exception->IsAssignableFrom(exception_class);
+      }
+      if (declares_exception) {
+        self->SetException(exception);
+      } else {
+        ThrowNewUndeclaredThrowableException(self, env, exception);
+      }
+    }
+  }
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc
new file mode 100644
index 0000000..cb224e8
--- /dev/null
+++ b/src/oat/runtime/support_stubs.cc
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2012 Google Inc. All Rights Reserved.
+ *
+ * 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 "callee_save_frame.h"
+#include "dex_instruction.h"
+#include "object.h"
+#include "object_utils.h"
+
+// Architecture specific assembler helper to deliver exception.
+extern "C" void art_deliver_exception_from_code(void*);
+
+namespace art {
+
+// Lazily resolve a method. Called by stub code.
+const void* UnresolvedDirectMethodTrampolineFromCode(Method* called, Method** sp, Thread* thread,
+                                                     Runtime::TrampolineType type) {
+  // TODO: this code is specific to ARM
+  // On entry the stack pointed by sp is:
+  // | argN       |  |
+  // | ...        |  |
+  // | arg4       |  |
+  // | arg3 spill |  |  Caller's frame
+  // | arg2 spill |  |
+  // | arg1 spill |  |
+  // | Method*    | ---
+  // | LR         |
+  // | ...        |    callee saves
+  // | R3         |    arg3
+  // | R2         |    arg2
+  // | R1         |    arg1
+  // | R0         |
+  // | Method*    |  <- sp
+  uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
+  DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
+  Method** caller_sp = reinterpret_cast<Method**>(reinterpret_cast<byte*>(sp) + 48);
+  uintptr_t caller_pc = regs[10];
+  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
+  // Start new JNI local reference state
+  JNIEnvExt* env = thread->GetJniEnv();
+  ScopedJniEnvLocalRefState env_state(env);
+
+  // Compute details about the called method (avoid GCs)
+  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  Method* caller = *caller_sp;
+  bool is_static;
+  bool is_virtual;
+  uint32_t dex_method_idx;
+  const char* shorty;
+  uint32_t shorty_len;
+  if (type == Runtime::kUnknownMethod) {
+    DCHECK(called->IsRuntimeMethod());
+    // less two as return address may span into next dex instruction
+    uint32_t dex_pc = caller->ToDexPC(caller_pc - 2);
+    const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
+    CHECK_LT(dex_pc, code->insns_size_in_code_units_);
+    const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
+    Instruction::Code instr_code = instr->Opcode();
+    is_static = (instr_code == Instruction::INVOKE_STATIC) ||
+                (instr_code == Instruction::INVOKE_STATIC_RANGE);
+    is_virtual = (instr_code == Instruction::INVOKE_VIRTUAL) ||
+                 (instr_code == Instruction::INVOKE_VIRTUAL_RANGE) ||
+                 (instr_code == Instruction::INVOKE_SUPER) ||
+                 (instr_code == Instruction::INVOKE_SUPER_RANGE);
+    DCHECK(is_static || is_virtual || (instr_code == Instruction::INVOKE_DIRECT) ||
+           (instr_code == Instruction::INVOKE_DIRECT_RANGE));
+    DecodedInstruction dec_insn(instr);
+    dex_method_idx = dec_insn.vB;
+    shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
+  } else {
+    DCHECK(!called->IsRuntimeMethod());
+    is_static = type == Runtime::kStaticMethod;
+    is_virtual = false;
+    dex_method_idx = called->GetDexMethodIndex();
+    MethodHelper mh(called);
+    shorty = mh.GetShorty();
+    shorty_len = mh.GetShortyLength();
+  }
+  // Discover shorty (avoid GCs)
+  size_t args_in_regs = 0;
+  for (size_t i = 1; i < shorty_len; i++) {
+    char c = shorty[i];
+    args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1);
+    if (args_in_regs > 3) {
+      args_in_regs = 3;
+      break;
+    }
+  }
+  // Place into local references incoming arguments from the caller's register arguments
+  size_t cur_arg = 1;   // skip method_idx in R0, first arg is in R1
+  if (!is_static) {
+    Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
+    cur_arg++;
+    if (args_in_regs < 3) {
+      // If we thought we had fewer than 3 arguments in registers, account for the receiver
+      args_in_regs++;
+    }
+    AddLocalReference<jobject>(env, obj);
+  }
+  size_t shorty_index = 1;  // skip return value
+  // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip
+  // R0)
+  while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) {
+    char c = shorty[shorty_index];
+    shorty_index++;
+    if (c == 'L') {
+      Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
+      AddLocalReference<jobject>(env, obj);
+    }
+    cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
+  }
+  // Place into local references incoming arguments from the caller's stack arguments
+  cur_arg += 11;  // skip LR, Method* and spills for R1 to R3 and callee saves
+  while (shorty_index < shorty_len) {
+    char c = shorty[shorty_index];
+    shorty_index++;
+    if (c == 'L') {
+      Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
+      AddLocalReference<jobject>(env, obj);
+    }
+    cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
+  }
+  // Resolve method filling in dex cache
+  if (type == Runtime::kUnknownMethod) {
+    called = linker->ResolveMethod(dex_method_idx, caller, !is_virtual);
+  }
+  const void* code = NULL;
+  if (LIKELY(!thread->IsExceptionPending())) {
+    if (LIKELY(called->IsDirect() == !is_virtual)) {
+      // Ensure that the called method's class is initialized.
+      Class* called_class = called->GetDeclaringClass();
+      linker->EnsureInitialized(called_class, true);
+      if (LIKELY(called_class->IsInitialized())) {
+        code = called->GetCode();
+      } else if (called_class->IsInitializing()) {
+        if (is_static) {
+          // Class is still initializing, go to oat and grab code (trampoline must be left in place
+          // until class is initialized to stop races between threads).
+          code = linker->GetOatCodeFor(called);
+        } else {
+          // No trampoline for non-static methods.
+          code = called->GetCode();
+        }
+      } else {
+        DCHECK(called_class->IsErroneous());
+      }
+    } else {
+      // Direct method has been made virtual
+      thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
+                                 "Expected direct method but found virtual: %s",
+                                 PrettyMethod(called, true).c_str());
+    }
+  }
+  if (UNLIKELY(code == NULL)) {
+    // Something went wrong in ResolveMethod or EnsureInitialized,
+    // go into deliver exception with the pending exception in r0
+    code = reinterpret_cast<void*>(art_deliver_exception_from_code);
+    regs[0] = reinterpret_cast<uintptr_t>(thread->GetException());
+    thread->ClearException();
+  } else {
+    // Expect class to at least be initializing.
+    DCHECK(called->GetDeclaringClass()->IsInitializing());
+    // Don't want infinite recursion.
+    DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
+    // Set up entry into main method
+    regs[0] = reinterpret_cast<uintptr_t>(called);
+  }
+  return code;
+}
+
+// Called by the AbstractMethodError. Called by stub code.
+extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp) {
+  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
+  thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
+                             "abstract method \"%s\"", PrettyMethod(method).c_str());
+  thread->DeliverException();
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_thread.cc b/src/oat/runtime/support_thread.cc
new file mode 100644
index 0000000..ed04673
--- /dev/null
+++ b/src/oat/runtime/support_thread.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 Google Inc. All Rights Reserved.
+ *
+ * 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 "callee_save_frame.h"
+#include "thread.h"
+#include "thread_list.h"
+
+namespace art {
+
+void CheckSuspendFromCode(Thread* thread) {
+  // Called when thread->suspend_count_ != 0
+  Runtime::Current()->GetThreadList()->FullSuspendCheck(thread);
+}
+
+extern "C" void artTestSuspendFromCode(Thread* thread, Method** sp) {
+  // Called when suspend count check value is 0 and thread->suspend_count_ != 0
+  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly);
+  Runtime::Current()->GetThreadList()->FullSuspendCheck(thread);
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_throw.cc b/src/oat/runtime/support_throw.cc
new file mode 100644
index 0000000..9f46b2b
--- /dev/null
+++ b/src/oat/runtime/support_throw.cc
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2012 Google Inc. All Rights Reserved.
+ *
+ * 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 "callee_save_frame.h"
+#include "dex_verifier.h"
+#include "object.h"
+#include "object_utils.h"
+#include "runtime_support.h"
+#include "thread.h"
+
+namespace art {
+
+// Deliver an exception that's pending on thread helping set up a callee save frame on the way.
+extern "C" void artDeliverPendingExceptionFromCode(Thread* thread, Method** sp) {
+  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
+  thread->DeliverException();
+}
+
+// Called by generated call to throw an exception.
+extern "C" void artDeliverExceptionFromCode(Throwable* exception, Thread* thread, Method** sp) {
+  /*
+   * exception may be NULL, in which case this routine should
+   * throw NPE.  NOTE: this is a convenience for generated code,
+   * which previously did the null check inline and constructed
+   * and threw a NPE if NULL.  This routine responsible for setting
+   * exception_ in thread and delivering the exception.
+   */
+  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
+  if (exception == NULL) {
+    thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
+  } else {
+    thread->SetException(exception);
+  }
+  thread->DeliverException();
+}
+
+// Called by generated call to throw a NPE exception.
+extern "C" void artThrowNullPointerExceptionFromCode(Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
+  Frame fr = self->GetTopOfStack();
+  uintptr_t throw_native_pc = fr.GetReturnPC();
+  fr.Next();
+  Method* throw_method = fr.GetMethod();
+  uint32_t dex_pc = throw_method->ToDexPC(throw_native_pc - 2);
+  const DexFile::CodeItem* code = MethodHelper(throw_method).GetCodeItem();
+  CHECK_LT(dex_pc, code->insns_size_in_code_units_);
+  const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
+  DecodedInstruction dec_insn(instr);
+  switch (instr->Opcode()) {
+    case Instruction::INVOKE_DIRECT:
+    case Instruction::INVOKE_DIRECT_RANGE:
+      ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kDirect);
+      break;
+    case Instruction::INVOKE_VIRTUAL:
+    case Instruction::INVOKE_VIRTUAL_RANGE:
+      ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kVirtual);
+      break;
+    case Instruction::IGET:
+    case Instruction::IGET_WIDE:
+    case Instruction::IGET_OBJECT:
+    case Instruction::IGET_BOOLEAN:
+    case Instruction::IGET_BYTE:
+    case Instruction::IGET_CHAR:
+    case Instruction::IGET_SHORT: {
+      Field* field =
+          Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
+      ThrowNullPointerExceptionForFieldAccess(self, field, true /* read */);
+      break;
+    }
+    case Instruction::IPUT:
+    case Instruction::IPUT_WIDE:
+    case Instruction::IPUT_OBJECT:
+    case Instruction::IPUT_BOOLEAN:
+    case Instruction::IPUT_BYTE:
+    case Instruction::IPUT_CHAR:
+    case Instruction::IPUT_SHORT: {
+      Field* field =
+          Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
+      ThrowNullPointerExceptionForFieldAccess(self, field, false /* write */);
+      break;
+    }
+    case Instruction::AGET:
+    case Instruction::AGET_WIDE:
+    case Instruction::AGET_OBJECT:
+    case Instruction::AGET_BOOLEAN:
+    case Instruction::AGET_BYTE:
+    case Instruction::AGET_CHAR:
+    case Instruction::AGET_SHORT:
+      self->ThrowNewException("Ljava/lang/NullPointerException;",
+                              "Attempt to read from null array");
+      break;
+    case Instruction::APUT:
+    case Instruction::APUT_WIDE:
+    case Instruction::APUT_OBJECT:
+    case Instruction::APUT_BOOLEAN:
+    case Instruction::APUT_BYTE:
+    case Instruction::APUT_CHAR:
+    case Instruction::APUT_SHORT:
+      self->ThrowNewException("Ljava/lang/NullPointerException;",
+                              "Attempt to write to null array");
+      break;
+    default: {
+      const DexFile& dex_file = Runtime::Current()->GetClassLinker()
+          ->FindDexFile(throw_method->GetDeclaringClass()->GetDexCache());
+      std::string message("Null pointer exception during instruction '");
+      message += instr->DumpString(&dex_file);
+      message += "'";
+      self->ThrowNewException("Ljava/lang/NullPointerException;", message.c_str());
+      break;
+    }
+  }
+  self->DeliverException();
+}
+
+// Called by generated call to throw an arithmetic divide by zero exception.
+extern "C" void artThrowDivZeroFromCode(Thread* thread, Method** sp) {
+  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
+  thread->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
+  thread->DeliverException();
+}
+
+// Called by generated call to throw an array index out of bounds exception.
+extern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread, Method** sp) {
+  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
+  thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
+                             "length=%d; index=%d", limit, index);
+  thread->DeliverException();
+}
+
+extern "C" void artThrowStackOverflowFromCode(Thread* thread, Method** sp) {
+  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
+  // Remove extra entry pushed onto second stack during method tracing
+  if (Runtime::Current()->IsMethodTracingActive()) {
+    TraceMethodUnwindFromCode(thread);
+  }
+  thread->SetStackEndForStackOverflow();  // Allow space on the stack for constructor to execute
+  thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;",
+      "stack size %zdkb; default stack size: %zdkb",
+      thread->GetStackSize() / KB, Runtime::Current()->GetDefaultStackSize() / KB);
+  thread->ResetDefaultStackEnd();  // Return to default stack size
+  thread->DeliverException();
+}
+
+extern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
+  Frame frame = self->GetTopOfStack();  // We need the calling method as context for the method_idx
+  frame.Next();
+  Method* method = frame.GetMethod();
+  self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
+      MethodNameFromIndex(method, method_idx, verifier::VERIFY_ERROR_REF_METHOD, false).c_str());
+  self->DeliverException();
+}
+
+static std::string ClassNameFromIndex(Method* method, uint32_t ref,
+                                      verifier::VerifyErrorRefType ref_type, bool access) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
+
+  uint16_t type_idx = 0;
+  if (ref_type == verifier::VERIFY_ERROR_REF_FIELD) {
+    const DexFile::FieldId& id = dex_file.GetFieldId(ref);
+    type_idx = id.class_idx_;
+  } else if (ref_type == verifier::VERIFY_ERROR_REF_METHOD) {
+    const DexFile::MethodId& id = dex_file.GetMethodId(ref);
+    type_idx = id.class_idx_;
+  } else if (ref_type == verifier::VERIFY_ERROR_REF_CLASS) {
+    type_idx = ref;
+  } else {
+    CHECK(false) << static_cast<int>(ref_type);
+  }
+
+  std::string class_name(PrettyDescriptor(dex_file.StringByTypeIdx(type_idx)));
+  if (!access) {
+    return class_name;
+  }
+
+  std::string result;
+  result += "tried to access class ";
+  result += class_name;
+  result += " from class ";
+  result += PrettyDescriptor(method->GetDeclaringClass());
+  return result;
+}
+
+extern "C" void artThrowVerificationErrorFromCode(int32_t kind, int32_t ref, Thread* self, Method** sp) {
+  FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
+  Frame frame = self->GetTopOfStack();  // We need the calling method as context to interpret 'ref'
+  frame.Next();
+  Method* method = frame.GetMethod();
+
+  verifier::VerifyErrorRefType ref_type =
+      static_cast<verifier::VerifyErrorRefType>(kind >> verifier::kVerifyErrorRefTypeShift);
+
+  const char* exception_class = "Ljava/lang/VerifyError;";
+  std::string msg;
+
+  switch (static_cast<verifier::VerifyError>(kind & ~(0xff << verifier::kVerifyErrorRefTypeShift))) {
+  case verifier::VERIFY_ERROR_NO_CLASS:
+    exception_class = "Ljava/lang/NoClassDefFoundError;";
+    msg = ClassNameFromIndex(method, ref, ref_type, false);
+    break;
+  case verifier::VERIFY_ERROR_NO_FIELD:
+    exception_class = "Ljava/lang/NoSuchFieldError;";
+    msg = FieldNameFromIndex(method, ref, ref_type, false);
+    break;
+  case verifier::VERIFY_ERROR_NO_METHOD:
+    exception_class = "Ljava/lang/NoSuchMethodError;";
+    msg = MethodNameFromIndex(method, ref, ref_type, false);
+    break;
+  case verifier::VERIFY_ERROR_ACCESS_CLASS:
+    exception_class = "Ljava/lang/IllegalAccessError;";
+    msg = ClassNameFromIndex(method, ref, ref_type, true);
+    break;
+  case verifier::VERIFY_ERROR_ACCESS_FIELD:
+    exception_class = "Ljava/lang/IllegalAccessError;";
+    msg = FieldNameFromIndex(method, ref, ref_type, true);
+    break;
+  case verifier::VERIFY_ERROR_ACCESS_METHOD:
+    exception_class = "Ljava/lang/IllegalAccessError;";
+    msg = MethodNameFromIndex(method, ref, ref_type, true);
+    break;
+  case verifier::VERIFY_ERROR_CLASS_CHANGE:
+    exception_class = "Ljava/lang/IncompatibleClassChangeError;";
+    msg = ClassNameFromIndex(method, ref, ref_type, false);
+    break;
+  case verifier::VERIFY_ERROR_INSTANTIATION:
+    exception_class = "Ljava/lang/InstantiationError;";
+    msg = ClassNameFromIndex(method, ref, ref_type, false);
+    break;
+  case verifier::VERIFY_ERROR_BAD_CLASS_SOFT:
+  case verifier::VERIFY_ERROR_BAD_CLASS_HARD:
+    // Generic VerifyError; use default exception, no message.
+    break;
+  case verifier::VERIFY_ERROR_NONE:
+    CHECK(false);
+    break;
+  }
+  self->ThrowNewException(exception_class, msg.c_str());
+  self->DeliverException();
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_trace.cc b/src/oat/runtime/support_trace.cc
new file mode 100644
index 0000000..5c6a46e
--- /dev/null
+++ b/src/oat/runtime/support_trace.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 Google Inc. All Rights Reserved.
+ *
+ * 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 "runtime.h"
+#include "thread.h"
+#include "trace.h"
+
+namespace art {
+
+extern "C" const void* artTraceMethodEntryFromCode(Method* method, Thread* self, uintptr_t lr) {
+  Trace* tracer = Runtime::Current()->GetTracer();
+  TraceStackFrame trace_frame = TraceStackFrame(method, lr);
+  self->PushTraceStackFrame(trace_frame);
+
+  tracer->LogMethodTraceEvent(self, method, Trace::kMethodTraceEnter);
+
+  return tracer->GetSavedCodeFromMap(method);
+}
+
+extern "C" uintptr_t artTraceMethodExitFromCode() {
+  Trace* tracer = Runtime::Current()->GetTracer();
+  TraceStackFrame trace_frame = Thread::Current()->PopTraceStackFrame();
+  Method* method = trace_frame.method_;
+  uintptr_t lr = trace_frame.return_pc_;
+
+  tracer->LogMethodTraceEvent(Thread::Current(), method, Trace::kMethodTraceExit);
+
+  return lr;
+}
+
+}  // namespace art
diff --git a/src/context_x86.cc b/src/oat/runtime/x86/context_x86.cc
similarity index 100%
rename from src/context_x86.cc
rename to src/oat/runtime/x86/context_x86.cc
diff --git a/src/context_x86.h b/src/oat/runtime/x86/context_x86.h
similarity index 87%
rename from src/context_x86.h
rename to src/oat/runtime/x86/context_x86.h
index 829849e..72dc719 100644
--- a/src/context_x86.h
+++ b/src/oat/runtime/x86/context_x86.h
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_CONTEXT_X86_H_
-#define ART_SRC_CONTEXT_X86_H_
-
-#include "context.h"
+#ifndef ART_SRC_OAT_RUNTIME_X86_CONTEXT_X86_H_
+#define ART_SRC_OAT_RUNTIME_X86_CONTEXT_X86_H_
 
 #include "constants_x86.h"
+#include "oat/runtime/context.h"
 
 namespace art {
 namespace x86 {
@@ -55,4 +54,4 @@
 }  // namespace x86
 }  // namespace art
 
-#endif  // ART_SRC_CONTEXT_X86_H_
+#endif  // ART_SRC_OAT_RUNTIME_X86_CONTEXT_X86_H_
diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
new file mode 100644
index 0000000..5d525a9
--- /dev/null
+++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
@@ -0,0 +1,234 @@
+/*
+ * 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 "oat/runtime/oat_support_entrypoints.h"
+
+namespace art {
+
+// Alloc entrypoints.
+extern "C" void* art_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_alloc_object_from_code(uint32_t type_idx, void* method);
+extern "C" void* art_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
+extern "C" void* art_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+
+// Cast entrypoints.
+extern uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class);
+extern "C" void art_can_put_array_element_from_code(void*, void*);
+extern "C" void art_check_cast_from_code(void*, void*);
+
+// Debug entrypoints.
+extern void DebugMe(Method* method, uint32_t info);
+
+// DexCache entrypoints.
+extern "C" void* art_initialize_static_storage_from_code(uint32_t, void*);
+extern "C" void* art_initialize_type_from_code(uint32_t, void*);
+extern "C" void* art_initialize_type_and_verify_access_from_code(uint32_t, void*);
+extern "C" void* art_resolve_string_from_code(void*, uint32_t);
+
+// Field entrypoints.
+extern "C" int art_set32_instance_from_code(uint32_t, void*, int32_t);
+extern "C" int art_set32_static_from_code(uint32_t, int32_t);
+extern "C" int art_set64_instance_from_code(uint32_t, void*, int64_t);
+extern "C" int art_set64_static_from_code(uint32_t, int64_t);
+extern "C" int art_set_obj_instance_from_code(uint32_t, void*, void*);
+extern "C" int art_set_obj_static_from_code(uint32_t, void*);
+extern "C" int32_t art_get32_instance_from_code(uint32_t, void*);
+extern "C" int32_t art_get32_static_from_code(uint32_t);
+extern "C" int64_t art_get64_instance_from_code(uint32_t, void*);
+extern "C" int64_t art_get64_static_from_code(uint32_t);
+extern "C" void* art_get_obj_instance_from_code(uint32_t, void*);
+extern "C" void* art_get_obj_static_from_code(uint32_t);
+
+// FillArray entrypoint.
+extern "C" void art_handle_fill_data_from_code(void*, void*);
+
+// JNI entrypoints.
+extern Object* DecodeJObjectInThread(Thread* thread, jobject obj);
+extern void* FindNativeMethod(Thread* thread);
+
+// Lock entrypoints.
+extern "C" void art_lock_object_from_code(void*);
+extern "C" void art_unlock_object_from_code(void*);
+
+// Math entrypoints.
+extern int32_t CmpgDouble(double a, double b);
+extern int32_t CmplDouble(double a, double b);
+extern int32_t CmpgFloat(float a, float b);
+extern int32_t CmplFloat(float a, float b);
+extern int64_t D2L(double d);
+extern int64_t F2L(float f);
+
+// Intrinsic entrypoints.
+extern "C" int32_t __memcmp16(void*, void*, int32_t);
+extern "C" int32_t art_indexof(void*, uint32_t, uint32_t, uint32_t);
+extern "C" int32_t art_string_compareto(void*, void*);
+
+// Invoke entrypoints.
+const void* UnresolvedDirectMethodTrampolineFromCode(Method*, Method**, Thread*,
+                                                     Runtime::TrampolineType);
+extern "C" void art_invoke_direct_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_interface_trampoline(uint32_t, void*);
+extern "C" void art_invoke_interface_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_static_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_super_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
+
+// Thread entrypoints.
+extern void CheckSuspendFromCode(Thread* thread);
+extern "C" void art_test_suspend();
+
+// Throw entrypoints.
+extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
+extern "C" void art_deliver_exception_from_code(void*);
+extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
+extern "C" void art_throw_div_zero_from_code();
+extern "C" void art_throw_no_such_method_from_code(int32_t method_idx);
+extern "C" void art_throw_null_pointer_exception_from_code();
+extern "C" void art_throw_stack_overflow_from_code(void*);
+extern "C" void art_throw_verification_error_from_code(int32_t src1, int32_t ref);
+
+void InitEntryPoints(EntryPoints* points) {
+  // Alloc
+  points->pAllocArrayFromCode = art_alloc_array_from_code;
+  points->pAllocArrayFromCodeWithAccessCheck = art_alloc_array_from_code_with_access_check;
+  points->pAllocObjectFromCode = art_alloc_object_from_code;
+  points->pAllocObjectFromCodeWithAccessCheck = art_alloc_object_from_code_with_access_check;
+  points->pCheckAndAllocArrayFromCode = art_check_and_alloc_array_from_code;
+  points->pCheckAndAllocArrayFromCodeWithAccessCheck = art_check_and_alloc_array_from_code_with_access_check;
+
+  // Cast
+  points->pInstanceofNonTrivialFromCode = IsAssignableFromCode;
+  points->pCanPutArrayElementFromCode = art_can_put_array_element_from_code;
+  points->pCheckCastFromCode = art_check_cast_from_code;
+
+  // Debug
+  points->pDebugMe = DebugMe;
+  points->pUpdateDebuggerFromCode = NULL; // Controlled by SetDebuggerUpdatesEnabled.
+
+  // DexCache
+  points->pInitializeStaticStorage = art_initialize_static_storage_from_code;
+  points->pInitializeTypeAndVerifyAccessFromCode = art_initialize_type_and_verify_access_from_code;
+  points->pInitializeTypeFromCode = art_initialize_type_from_code;
+  points->pResolveStringFromCode = art_resolve_string_from_code;
+
+  // Field
+  points->pSet32Instance = art_set32_instance_from_code;
+  points->pSet32Static = art_set32_static_from_code;
+  points->pSet64Instance = art_set64_instance_from_code;
+  points->pSet64Static = art_set64_static_from_code;
+  points->pSetObjInstance = art_set_obj_instance_from_code;
+  points->pSetObjStatic = art_set_obj_static_from_code;
+  points->pGet32Instance = art_get32_instance_from_code;
+  points->pGet64Instance = art_get64_instance_from_code;
+  points->pGetObjInstance = art_get_obj_instance_from_code;
+  points->pGet32Static = art_get32_static_from_code;
+  points->pGet64Static = art_get64_static_from_code;
+  points->pGetObjStatic = art_get_obj_static_from_code;
+
+  // FillArray
+  points->pHandleFillArrayDataFromCode = art_handle_fill_data_from_code;
+
+  // JNI
+  points->pDecodeJObjectInThread = DecodeJObjectInThread;
+  points->pFindNativeMethod = FindNativeMethod;
+
+  // Locks
+  points->pLockObjectFromCode = art_lock_object_from_code;
+  points->pUnlockObjectFromCode = art_unlock_object_from_code;
+
+  // Math
+  points->pCmpgDouble = CmpgDouble;
+  points->pCmpgFloat = CmpgFloat;
+  points->pCmplDouble = CmplDouble;
+  points->pCmplFloat = CmplFloat;
+  points->pDadd = NULL;
+  points->pDdiv = NULL;
+  points->pDmul = NULL;
+  points->pDsub = NULL;
+  points->pF2d = NULL;
+  points->pFmod = NULL;
+  points->pI2d = NULL;
+  points->pL2d = NULL;
+  points->pD2f = NULL;
+  points->pFadd = NULL;
+  points->pFdiv = NULL;
+  points->pFmodf = NULL;
+  points->pFmul = NULL;
+  points->pFsub = NULL;
+  points->pI2f = NULL;
+  points->pL2f = NULL;
+  points->pD2iz = NULL;
+  points->pF2iz = NULL;
+  points->pIdiv = NULL;
+  points->pIdivmod = NULL;
+  points->pD2l = D2L;
+  points->pF2l = F2L;
+  points->pLadd = NULL;
+  points->pLand = NULL;
+  points->pLdivmod = NULL;
+  points->pLmul = NULL;
+  points->pLor = NULL;
+  points->pLsub = NULL;
+  points->pLxor = NULL;
+  points->pShlLong = NULL;
+  points->pShrLong = NULL;
+  points->pUshrLong = NULL;
+
+  // Intrinsics
+  points->pIndexOf = art_indexof;
+  points->pMemcmp16 = __memcmp16;
+  points->pStringCompareTo = art_string_compareto;
+  points->pMemcpy = memcpy;
+
+  // Invocation
+  points->pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
+  points->pInvokeDirectTrampolineWithAccessCheck = art_invoke_direct_trampoline_with_access_check;
+  points->pInvokeInterfaceTrampoline = art_invoke_interface_trampoline;
+  points->pInvokeInterfaceTrampolineWithAccessCheck = art_invoke_interface_trampoline_with_access_check;
+  points->pInvokeStaticTrampolineWithAccessCheck = art_invoke_static_trampoline_with_access_check;
+  points->pInvokeSuperTrampolineWithAccessCheck = art_invoke_super_trampoline_with_access_check;
+  points->pInvokeVirtualTrampolineWithAccessCheck = art_invoke_virtual_trampoline_with_access_check;
+
+  // Thread
+  points->pCheckSuspendFromCode = CheckSuspendFromCode;
+  points->pTestSuspendFromCode = art_test_suspend;
+
+  // Throws
+  points->pDeliverException = art_deliver_exception_from_code;
+  points->pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode;
+  points->pThrowArrayBoundsFromCode = art_throw_array_bounds_from_code;
+  points->pThrowDivZeroFromCode = art_throw_div_zero_from_code;
+  points->pThrowNoSuchMethodFromCode = art_throw_no_such_method_from_code;
+  points->pThrowNullPointerFromCode = art_throw_null_pointer_exception_from_code;
+  points->pThrowStackOverflowFromCode = art_throw_stack_overflow_from_code;
+  points->pThrowVerificationErrorFromCode = art_throw_verification_error_from_code;
+};
+
+void ChangeDebuggerEntryPoint(EntryPoints*, bool) {
+  UNIMPLEMENTED(FATAL);
+}
+
+bool IsTraceExitPc(uintptr_t) {
+  return false;
+}
+
+void* GetLogTraceEntryPoint() {
+  return NULL;
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/x86/runtime_support_x86.S b/src/oat/runtime/x86/runtime_support_x86.S
new file mode 100644
index 0000000..d344c34
--- /dev/null
+++ b/src/oat/runtime/x86/runtime_support_x86.S
@@ -0,0 +1,321 @@
+#include "asm_support.h"
+
+#if defined(__APPLE__)
+    // Mac OS X mangles the functions with an underscore prefix
+    #define art_deliver_exception_from_code _art_deliver_exception_from_code
+    #define art_proxy_invoke_handler _art_proxy_invoke_handler
+    #define artDeliverExceptionFromCode _artDeliverExceptionFromCode
+#endif
+
+    /* Deliver the given exception */
+    .extern artDeliverExceptionFromCode
+    /* Deliver an exception pending on a thread */
+    .extern artDeliverPendingException
+
+    /* Cache alignment for function entry */
+.macro ALIGN_FUNCTION_ENTRY
+    .balign 16
+.endm
+
+    /*
+     * Macro that sets up the callee save frame to conform with
+     * Runtime::CreateCalleeSaveMethod(...)
+     */
+.macro SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
+    pushl %edi  // Save callee saves (ebx is saved/restored by the upcall)
+    pushl %esi
+    pushl %ebp
+    subl  $16, %esp  // Grow stack by 4 words, bottom word will hold Method*
+.endm
+
+.macro RESTORE_CALLEE_SAVE_FRAME
+    addl $16, %esp  // Remove padding
+    popl %ebp  // Restore callee saves
+    popl %esi
+    popl %edi
+.endm
+
+    /*
+     * Macro that sets up the callee save frame to conform with
+     * Runtime::CreateCalleeSaveMethod(...)
+     */
+.macro SETUP_REF_AND_ARG_CALLEE_SAVE_FRAME
+    pushl %edi  // Save callee saves
+    pushl %esi
+    pushl %ebp
+    pushl %ebx  // Save args
+    pushl %edx
+    pushl %ecx
+    pushl %eax  // Align stack, eax will be clobbered by Method*
+.endm
+
+.macro RESTORE_REF_AND_ARG_CALLEE_SAVE_FRAME
+    addl $16, %esp  // Remove padding
+    popl %ebp  // Restore callee saves
+    popl %esi
+    popl %edi
+.endm
+
+    /*
+     * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
+     * exception is Thread::Current()->exception_.
+     */
+.macro DELIVER_PENDING_EXCEPTION
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME         // save callee saves for throw
+    mov %esp, %ecx
+    // Outgoing argument set up
+    subl  $8, %esp                           // Alignment padding
+    pushl %ecx                               // pass SP
+    pushl %fs:THREAD_SELF_OFFSET             // pass Thread::Current()
+    call artDeliverPendingExceptionFromCode  // artDeliverExceptionFromCode(Thread*, SP)
+    int3
+.endm
+
+.macro NO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
+    .global \c_name
+    .extern \cxx_name
+    ALIGN_FUNCTION_ENTRY
+\c_name:
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
+    mov %esp, %ecx
+    // Outgoing argument set up
+    subl  $8, %esp                // alignment padding
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    pushl %ecx                    // pass SP
+    call \cxx_name                // \cxx_name(Thread*, SP)
+    int3                          // unreached
+.endm
+
+.macro ONE_ARG_RUNTIME_EXCEPTION c_name, cxx_name
+    .global \c_name
+    .extern \cxx_name
+    ALIGN_FUNCTION_ENTRY
+\c_name:
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
+    mov %esp, %ecx
+    // Outgoing argument set up
+    pushl $0                      // alignment padding
+    pushl %ecx                    // pass SP
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    pushl %eax                    // pass arg1
+    call \cxx_name                // \cxx_name(arg1, Thread*, SP)
+    int3                          // unreached
+.endm
+
+.macro TWO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
+    .global \c_name
+    .extern \cxx_name
+    ALIGN_FUNCTION_ENTRY
+\c_name:
+    SETUP_SAVE_ALL_CALLEE_SAVE_FRAME  // save all registers as basis for long jump context
+    mov %esp, %edx
+    // Outgoing argument set up
+    pushl %edx                    // pass SP
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    pushl %eax                    // pass arg1
+    pushl %ecx                    // pass arg2
+    call \cxx_name                // \cxx_name(arg1, Thread*, SP)
+    int3                          // unreached
+.endm
+
+    /*
+     * Called by managed code, saves callee saves and then calls artThrowException
+     * that will place a mock Method* at the bottom of the stack. Arg1 holds the exception.
+     */
+ONE_ARG_RUNTIME_EXCEPTION art_deliver_exception_from_code, artDeliverExceptionFromCode
+
+    /*
+     * Called by managed code to create and deliver a NullPointerException.
+     */
+NO_ARG_RUNTIME_EXCEPTION art_throw_null_pointer_exception_from_code, artThrowNullPointerExceptionFromCode
+
+    /*
+     * Called by managed code to create and deliver an ArithmeticException.
+     */
+NO_ARG_RUNTIME_EXCEPTION art_throw_div_zero_from_code, artThrowDivZeroFromCode
+
+    /*
+     * Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
+     * index, arg2 holds limit.
+     */
+TWO_ARG_RUNTIME_EXCEPTION art_throw_array_bounds_from_code, artThrowArrayBoundsFromCode
+
+    /*
+     * Called by managed code to create and deliver a StackOverflowError.
+     */
+NO_ARG_RUNTIME_EXCEPTION art_throw_stack_overflow_from_code, artThrowStackOverflowFromCode
+
+    /*
+     * Called by managed code to create and deliver a NoSuchMethodError.
+     */
+ONE_ARG_RUNTIME_EXCEPTION art_throw_no_such_method_from_code, artThrowNoSuchMethodFromCode
+
+    /*
+     * Called by managed code to create and deliver verification errors. Arg1 is kind, arg2 is ref.
+     */
+TWO_ARG_RUNTIME_EXCEPTION art_throw_verification_error_from_code, artThrowVerificationErrorFromCode
+
+    /*
+     * All generated callsites for interface invokes and invocation slow paths will load arguments
+     * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
+     * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
+     * stack and call the appropriate C helper.
+     * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1.
+     *
+     * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
+     * of the target Method* in r0 and method->code_ in r1.
+     *
+     * If unsuccessful, the helper will return NULL/NULL. There will bea pending exception in the
+     * thread and we branch to another stub to deliver it.
+     *
+     * On success this wrapper will restore arguments and *jump* to the target, leaving the lr
+     * pointing back to the original caller.
+     */
+.macro INVOKE_TRAMPOLINE c_name, cxx_name
+    .global \c_name
+    .extern \cxx_name
+    ALIGN_FUNCTION_ENTRY
+\c_name:
+    int3
+.endm
+
+INVOKE_TRAMPOLINE art_invoke_interface_trampoline, artInvokeInterfaceTrampoline
+INVOKE_TRAMPOLINE art_invoke_interface_trampoline_with_access_check, artInvokeInterfaceTrampolineWithAccessCheck
+
+INVOKE_TRAMPOLINE art_invoke_static_trampoline_with_access_check, artInvokeStaticTrampolineWithAccessCheck
+INVOKE_TRAMPOLINE art_invoke_direct_trampoline_with_access_check, artInvokeDirectTrampolineWithAccessCheck
+INVOKE_TRAMPOLINE art_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
+INVOKE_TRAMPOLINE art_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
+
+    // TODO
+    .globl art_proxy_invoke_handler
+art_proxy_invoke_handler:
+    int3
+
+    .globl art_update_debugger
+art_update_debugger:
+    int3
+
+   .globl art_test_suspend
+art_test_suspend:
+    int3
+
+   .globl art_alloc_object_from_code
+art_alloc_object_from_code:
+    int3
+
+   .globl art_alloc_object_from_code_with_access_check
+art_alloc_object_from_code_with_access_check:
+    int3
+
+   .globl art_alloc_array_from_code
+art_alloc_array_from_code:
+    int3
+
+   .globl art_alloc_array_from_code_with_access_check
+art_alloc_array_from_code_with_access_check:
+    int3
+
+   .globl art_check_and_alloc_array_from_code
+art_check_and_alloc_array_from_code:
+    int3
+
+   .globl art_check_and_alloc_array_from_code_with_access_check
+art_check_and_alloc_array_from_code_with_access_check:
+    int3
+
+   .globl art_can_put_array_element_from_code
+art_can_put_array_element_from_code:
+    int3
+
+   .globl art_check_cast_from_code
+art_check_cast_from_code:
+    int3
+
+   .globl art_initialize_static_storage_from_code
+art_initialize_static_storage_from_code:
+    int3
+
+   .globl art_initialize_type_and_verify_access_from_code
+art_initialize_type_and_verify_access_from_code:
+    int3
+
+   .globl art_initialize_type_from_code
+art_initialize_type_from_code:
+    int3
+
+   .globl art_resolve_string_from_code
+art_resolve_string_from_code:
+    int3
+
+   .globl art_set32_instance_from_code
+art_set32_instance_from_code:
+    int3
+
+   .globl art_set64_instance_from_code
+art_set64_instance_from_code:
+    int3
+
+   .globl art_set_obj_instance_from_code
+art_set_obj_instance_from_code:
+    int3
+
+   .globl art_get32_instance_from_code
+art_get32_instance_from_code:
+    int3
+
+   .globl art_get64_instance_from_code
+art_get64_instance_from_code:
+    int3
+
+   .globl art_get_obj_instance_from_code
+art_get_obj_instance_from_code:
+    int3
+
+   .globl art_set32_static_from_code
+art_set32_static_from_code:
+    int3
+
+   .globl art_set64_static_from_code
+art_set64_static_from_code:
+    int3
+
+   .globl art_set_obj_static_from_code
+art_set_obj_static_from_code:
+    int3
+
+   .globl art_get32_static_from_code
+art_get32_static_from_code:
+    int3
+
+   .globl art_get64_static_from_code
+art_get64_static_from_code:
+    int3
+
+   .globl art_get_obj_static_from_code
+art_get_obj_static_from_code:
+    int3
+
+    .globl art_handle_fill_data_from_code
+art_handle_fill_data_from_code:
+    int3
+
+    .globl art_lock_object_from_code
+art_lock_object_from_code:
+    int3
+
+    .globl art_unlock_object_from_code
+art_unlock_object_from_code:
+    int3
+
+    .globl art_indexof
+art_indexof:
+    int3
+
+    .globl __memcmp16
+__memcmp16:
+    int3
+
+    .globl art_string_compareto
+art_string_compareto:
+    int3
diff --git a/src/stub_x86.cc b/src/oat/runtime/x86/stub_x86.cc
similarity index 93%
rename from src/stub_x86.cc
rename to src/oat/runtime/x86/stub_x86.cc
index b07cfea..14e4f23 100644
--- a/src/stub_x86.cc
+++ b/src/oat/runtime/x86/stub_x86.cc
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#include "assembler_x86.h"
 #include "jni_internal.h"
+#include "oat/runtime/oat_support_entrypoints.h"
+#include "oat/utils/x86/assembler_x86.h"
 #include "object.h"
 #include "stack_indirect_reference_table.h"
 
@@ -60,7 +61,7 @@
   __ pushl(EAX);           // pass Method*
 
   // Call to throw AbstractMethodError.
-  __ Call(ThreadOffset(OFFSETOF_MEMBER(Thread, pThrowAbstractMethodErrorFromCode)),
+  __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pThrowAbstractMethodErrorFromCode)),
           X86ManagedRegister::FromCpuRegister(ECX));
 
 #if defined(ART_USE_LLVM_COMPILER)
@@ -94,7 +95,7 @@
   __ pushl(Immediate(0));
   __ fs()->pushl(Address::Absolute(Thread::SelfOffset()));  // Thread*
 
-  __ Call(ThreadOffset(OFFSETOF_MEMBER(Thread, pFindNativeMethod)),
+  __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pFindNativeMethod)),
           X86ManagedRegister::FromCpuRegister(ECX));
 
   __ addl(ESP, Immediate(12));
diff --git a/src/assembler_arm.cc b/src/oat/utils/arm/assembler_arm.cc
similarity index 99%
rename from src/assembler_arm.cc
rename to src/oat/utils/arm/assembler_arm.cc
index 65f8e57..2392c7d 100644
--- a/src/assembler_arm.cc
+++ b/src/oat/utils/arm/assembler_arm.cc
@@ -17,6 +17,7 @@
 #include "assembler_arm.h"
 
 #include "logging.h"
+#include "oat/runtime/oat_support_entrypoints.h"
 #include "offsets.h"
 #include "thread.h"
 #include "utils.h"
@@ -1885,7 +1886,7 @@
   __ Store(return_save_location_, return_register_, return_size_);
   // Pass thread as argument
   __ mov(R0, ShifterOperand(TR));
-  __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pCheckSuspendFromCode));
+  __ LoadFromOffset(kLoadWord, R12, TR, ENTRYPOINT_OFFSET(pCheckSuspendFromCode));
   // Note: assume that link register will be spilled/filled on method entry/exit
   __ blx(R12);
   // Reload return value
@@ -1913,7 +1914,7 @@
   // Don't care about preserving R0 as this call won't return
   __ mov(R0, ShifterOperand(scratch_.AsCoreRegister()));
   // Set up call to Thread::Current()->pDeliverException
-  __ LoadFromOffset(kLoadWord, R12, TR, OFFSETOF_MEMBER(Thread, pDeliverException));
+  __ LoadFromOffset(kLoadWord, R12, TR, ENTRYPOINT_OFFSET(pDeliverException));
   __ blx(R12);
   // Call never returns
   __ bkpt(0);
diff --git a/src/assembler_arm.h b/src/oat/utils/arm/assembler_arm.h
similarity index 98%
rename from src/assembler_arm.h
rename to src/oat/utils/arm/assembler_arm.h
index c557a36..d26fc1f 100644
--- a/src/assembler_arm.h
+++ b/src/oat/utils/arm/assembler_arm.h
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_ASSEMBLER_ARM_H_
-#define ART_SRC_ASSEMBLER_ARM_H_
+#ifndef ART_SRC_OAT_UTILS_ARM_ASSEMBLER_ARM_H_
+#define ART_SRC_OAT_UTILS_ARM_ASSEMBLER_ARM_H_
 
-#include "assembler.h"
 #include "constants.h"
-#include "managed_register_arm.h"
 #include "logging.h"
+#include "oat/utils/arm/managed_register_arm.h"
+#include "oat/utils/assembler.h"
 #include "offsets.h"
 #include "utils.h"
 #include <vector>
@@ -670,4 +670,4 @@
 }  // namespace arm
 }  // namespace art
 
-#endif  // ART_SRC_ASSEMBLER_ARM_H_
+#endif  // ART_SRC_OAT_UTILS_ARM_ASSEMBLER_ARM_H_
diff --git a/src/managed_register_arm.cc b/src/oat/utils/arm/managed_register_arm.cc
similarity index 98%
rename from src/managed_register_arm.cc
rename to src/oat/utils/arm/managed_register_arm.cc
index 272c52b..57c2305 100644
--- a/src/managed_register_arm.cc
+++ b/src/oat/utils/arm/managed_register_arm.cc
@@ -17,7 +17,6 @@
 #include "managed_register_arm.h"
 
 #include "globals.h"
-#include "calling_convention.h"
 
 namespace art {
 namespace arm {
diff --git a/src/managed_register_arm.h b/src/oat/utils/arm/managed_register_arm.h
similarity index 97%
rename from src/managed_register_arm.h
rename to src/oat/utils/arm/managed_register_arm.h
index 3576b5a..8808d2b 100644
--- a/src/managed_register_arm.h
+++ b/src/oat/utils/arm/managed_register_arm.h
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_MANAGED_REGISTER_ARM_H_
-#define ART_SRC_MANAGED_REGISTER_ARM_H_
+#ifndef ART_SRC_OAT_UTILS_ARM_MANAGED_REGISTER_ARM_H_
+#define ART_SRC_OAT_UTILS_ARM_MANAGED_REGISTER_ARM_H_
 
 #include "constants.h"
 #include "logging.h"
-#include "managed_register.h"
+#include "oat/utils/managed_register.h"
 
 namespace art {
 namespace arm {
@@ -271,4 +271,4 @@
 
 }  // namespace art
 
-#endif  // ART_SRC_MANAGED_REGISTER_ARM_H_
+#endif  // ART_SRC_OAT_UTILS_ARM_MANAGED_REGISTER_ARM_H_
diff --git a/src/managed_register_arm_test.cc b/src/oat/utils/arm/managed_register_arm_test.cc
similarity index 100%
rename from src/managed_register_arm_test.cc
rename to src/oat/utils/arm/managed_register_arm_test.cc
diff --git a/src/assembler.cc b/src/oat/utils/assembler.cc
similarity index 97%
rename from src/assembler.cc
rename to src/oat/utils/assembler.cc
index 2adf30b..249a771 100644
--- a/src/assembler.cc
+++ b/src/oat/utils/assembler.cc
@@ -19,8 +19,8 @@
 #include <algorithm>
 #include <vector>
 
-#include "assembler_arm.h"
-#include "assembler_x86.h"
+#include "arm/assembler_arm.h"
+#include "x86/assembler_x86.h"
 #include "globals.h"
 #include "memory_region.h"
 
diff --git a/src/assembler.h b/src/oat/utils/assembler.h
similarity index 98%
rename from src/assembler.h
rename to src/oat/utils/assembler.h
index af9f94d..6fd150d 100644
--- a/src/assembler.h
+++ b/src/oat/utils/assembler.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_ASSEMBLER_H_
-#define ART_SRC_ASSEMBLER_H_
+#ifndef ART_SRC_OAT_UTILS_ASSEMBLER_H_
+#define ART_SRC_OAT_UTILS_ASSEMBLER_H_
 
 #include <vector>
 
@@ -450,7 +450,4 @@
 
 }  // namespace art
 
-#include "assembler_x86.h"
-#include "assembler_arm.h"
-
-#endif  // ART_SRC_ASSEMBLER_H_
+#endif  // ART_SRC_OAT_UTILS_ASSEMBLER_H_
diff --git a/src/managed_register.h b/src/oat/utils/managed_register.h
similarity index 91%
rename from src/managed_register.h
rename to src/oat/utils/managed_register.h
index e9236b9..c0fbd21 100644
--- a/src/managed_register.h
+++ b/src/oat/utils/managed_register.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_MANAGED_REGISTER_H_
-#define ART_SRC_MANAGED_REGISTER_H_
+#ifndef ART_SRC_OAT_UTILS_MANAGED_REGISTER_H_
+#define ART_SRC_OAT_UTILS_MANAGED_REGISTER_H_
 
 namespace art {
 
@@ -65,4 +65,4 @@
 
 }  // namespace art
 
-#endif  // ART_SRC_MANAGED_REGISTER_H_
+#endif  // ART_SRC_OAT_UTILS_MANAGED_REGISTER_H_
diff --git a/src/assembler_x86.cc b/src/oat/utils/x86/assembler_x86.cc
similarity index 99%
rename from src/assembler_x86.cc
rename to src/oat/utils/x86/assembler_x86.cc
index ea283ce..0862551 100644
--- a/src/assembler_x86.cc
+++ b/src/oat/utils/x86/assembler_x86.cc
@@ -18,6 +18,7 @@
 
 #include "casts.h"
 #include "memory_region.h"
+#include "oat/runtime/oat_support_entrypoints.h"
 #include "thread.h"
 
 namespace art {
@@ -1815,7 +1816,7 @@
   __ Store(return_save_location_, return_register_, return_size_);
   // Pass Thread::Current as argument
   __ fs()->pushl(Address::Absolute(Thread::SelfOffset()));
-  __ fs()->call(Address::Absolute(OFFSETOF_MEMBER(Thread, pCheckSuspendFromCode)));
+  __ fs()->call(Address::Absolute(ENTRYPOINT_OFFSET(pCheckSuspendFromCode)));
   // Release argument
   __ addl(ESP, Immediate(kPointerSize));
   // Reload return value
@@ -1838,7 +1839,7 @@
   // Note: the return value is dead
   // Pass exception as argument in EAX
   __ fs()->movl(EAX, Address::Absolute(Thread::ExceptionOffset()));
-  __ fs()->call(Address::Absolute(OFFSETOF_MEMBER(Thread, pDeliverException)));
+  __ fs()->call(Address::Absolute(ENTRYPOINT_OFFSET(pDeliverException)));
   // this call should never return
   __ int3();
 #undef __
diff --git a/src/assembler_x86.h b/src/oat/utils/x86/assembler_x86.h
similarity index 98%
rename from src/assembler_x86.h
rename to src/oat/utils/x86/assembler_x86.h
index 24a84e7..f7d26ff 100644
--- a/src/assembler_x86.h
+++ b/src/oat/utils/x86/assembler_x86.h
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_ASSEMBLER_X86_H_
-#define ART_SRC_ASSEMBLER_X86_H_
+#ifndef ART_SRC_OAT_UTILS_X86_ASSEMBLER_X86_H_
+#define ART_SRC_OAT_UTILS_X86_ASSEMBLER_X86_H_
 
 #include <vector>
-#include "assembler.h"
 #include "constants.h"
 #include "globals.h"
 #include "managed_register_x86.h"
 #include "macros.h"
+#include "oat/utils/assembler.h"
 #include "offsets.h"
 #include "utils.h"
 
@@ -666,4 +666,4 @@
 }  // namespace x86
 }  // namespace art
 
-#endif  // ART_SRC_ASSEMBLER_X86_H_
+#endif  // ART_SRC_OAT_UTILS_X86_ASSEMBLER_X86_H_
diff --git a/src/assembler_x86_test.cc b/src/oat/utils/x86/assembler_x86_test.cc
similarity index 100%
rename from src/assembler_x86_test.cc
rename to src/oat/utils/x86/assembler_x86_test.cc
diff --git a/src/managed_register_x86.cc b/src/oat/utils/x86/managed_register_x86.cc
similarity index 97%
rename from src/managed_register_x86.cc
rename to src/oat/utils/x86/managed_register_x86.cc
index 453cab7..4697d06 100644
--- a/src/managed_register_x86.cc
+++ b/src/oat/utils/x86/managed_register_x86.cc
@@ -17,13 +17,12 @@
 #include "managed_register_x86.h"
 
 #include "globals.h"
-#include "calling_convention.h"
 
 namespace art {
 namespace x86 {
 
 // These cpu registers are never available for allocation.
-static const Register kReservedCpuRegistersArray[] = { EBP, ESP };
+static const Register kReservedCpuRegistersArray[] = { ESP };
 
 
 // We reduce the number of available registers for allocation in debug-code
diff --git a/src/managed_register_x86.h b/src/oat/utils/x86/managed_register_x86.h
similarity index 96%
rename from src/managed_register_x86.h
rename to src/oat/utils/x86/managed_register_x86.h
index edbf852..33573f9 100644
--- a/src/managed_register_x86.h
+++ b/src/oat/utils/x86/managed_register_x86.h
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_MANAGED_REGISTER_X86_H_
-#define ART_SRC_MANAGED_REGISTER_X86_H_
+#ifndef ART_SRC_OAT_UTILS_X86_MANAGED_REGISTER_X86_H_
+#define ART_SRC_OAT_UTILS_X86_MANAGED_REGISTER_X86_H_
 
 #include "constants_x86.h"
-#include "managed_register.h"
+#include "oat/utils/managed_register.h"
 
 namespace art {
 namespace x86 {
@@ -209,4 +209,4 @@
 
 }  // namespace art
 
-#endif  // ART_SRC_MANAGED_REGISTER_X86_H_
+#endif  // ART_SRC_OAT_UTILS_X86_MANAGED_REGISTER_X86_H_
diff --git a/src/managed_register_x86_test.cc b/src/oat/utils/x86/managed_register_x86_test.cc
similarity index 100%
rename from src/managed_register_x86_test.cc
rename to src/oat/utils/x86/managed_register_x86_test.cc
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 2dcf5b9..52763c6 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -24,12 +24,12 @@
 #include <vector>
 
 #include "class_linker.h"
-#include "context.h"
 #include "dex_instruction.h"
 #include "dex_verifier.h"
 #include "disassembler.h"
 #include "file.h"
 #include "image.h"
+#include "oat/runtime/context.h"  // For VmapTable
 #include "object_utils.h"
 #include "os.h"
 #include "runtime.h"
diff --git a/src/object.h b/src/object.h
index ad8194a..426a48c 100644
--- a/src/object.h
+++ b/src/object.h
@@ -861,8 +861,17 @@
     SetField32(OFFSET_OF_OBJECT_MEMBER(Method, fp_spill_mask_), fp_spill_mask, false);
   }
 
+  // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
+  // conventions for a method of managed code.
+  bool IsRuntimeMethod() const {
+    return GetDexMethodIndex() == DexFile::kDexNoIndex16;
+  }
+
   // Is this a hand crafted method used for something like describing callee saves?
   bool IsCalleeSaveMethod() const {
+    if (!IsRuntimeMethod()) {
+      return false;
+    }
     Runtime* runtime = Runtime::Current();
     bool result = false;
     for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
@@ -871,8 +880,6 @@
         break;
       }
     }
-    // Check that if we do think it is phony it looks like the callee save method
-    DCHECK(!result || GetDexMethodIndex() == DexFile::kDexNoIndex16);
     return result;
   }
 
@@ -883,12 +890,6 @@
     return result;
   }
 
-  // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
-  // conventions for a method of managed code.
-  bool IsRuntimeMethod() const {
-    return GetDexMethodIndex() == DexFile::kDexNoIndex16;
-  }
-
   // Converts a native PC to a dex PC.  TODO: this is a no-op
   // until we associate a PC mapping table with each method.
   uint32_t ToDexPC(const uintptr_t pc) const;
diff --git a/src/object_test.cc b/src/object_test.cc
index bf07aa3..de32f69 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -386,11 +386,6 @@
   ASSERT_TRUE(x.get() != NULL);
   ASSERT_TRUE(y.get() != NULL);
 
-  EXPECT_EQ(1U, IsAssignableFromCode(X, x->GetClass()));
-  EXPECT_EQ(0U, IsAssignableFromCode(Y, x->GetClass()));
-  EXPECT_EQ(1U, IsAssignableFromCode(X, y->GetClass()));
-  EXPECT_EQ(1U, IsAssignableFromCode(Y, y->GetClass()));
-
   EXPECT_TRUE(x->InstanceOf(X));
   EXPECT_FALSE(x->InstanceOf(Y));
   EXPECT_TRUE(y->InstanceOf(X));
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index a55c55c..9072d58 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 Google Inc. All Rights Reserved.
+ * Copyright 2012 Google Inc. All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,250 +16,98 @@
 
 #include "runtime_support.h"
 
-#include "debugger.h"
-#include "dex_cache.h"
-#include "dex_verifier.h"
-#include "macros.h"
-#include "object.h"
-#include "object_utils.h"
-#include "reflection.h"
-#include "runtime_support_common.h"
-#include "trace.h"
-#include "ScopedLocalRef.h"
-
 namespace art {
 
-// Place a special frame at the TOS that will save the callee saves for the given type
-static void  FinishCalleeSaveFrameSetup(Thread* self, Method** sp, Runtime::CalleeSaveType type) {
-  // Be aware the store below may well stomp on an incoming argument
-  *sp = Runtime::Current()->GetCalleeSaveMethod(type);
-  self->SetTopOfStack(sp, 0);
-  self->VerifyStack();
+void ThrowNewIllegalAccessErrorClass(Thread* self,
+                                     Class* referrer,
+                                     Class* accessed) {
+  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
+                           "illegal class access: '%s' -> '%s'",
+                           PrettyDescriptor(referrer).c_str(),
+                           PrettyDescriptor(accessed).c_str());
 }
 
-/*
- * Report location to debugger.  Note: dex_pc is the current offset within
- * the method.  However, because the offset alone cannot distinguish between
- * method entry and offset 0 within the method, we'll use an offset of -1
- * to denote method entry.
- */
-extern "C" void artUpdateDebuggerFromCode(int32_t dex_pc, Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp,  Runtime::kRefsAndArgs);
-  Dbg::UpdateDebugger(dex_pc, self, sp);
+void ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self,
+                                                      Class* referrer,
+                                                      Class* accessed,
+                                                      const Method* caller,
+                                                      const Method* called,
+                                                      InvokeType type) {
+  std::ostringstream type_stream;
+  type_stream << type;
+  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
+                           "illegal class access ('%s' -> '%s')"
+                           "in attempt to invoke %s method '%s' from '%s'",
+                           PrettyDescriptor(referrer).c_str(),
+                           PrettyDescriptor(accessed).c_str(),
+                           type_stream.str().c_str(),
+                           PrettyMethod(called).c_str(),
+                           PrettyMethod(caller).c_str());
 }
 
-// Temporary debugging hook for compiler.
-extern void DebugMe(Method* method, uint32_t info) {
-  LOG(INFO) << "DebugMe";
-  if (method != NULL) {
-    LOG(INFO) << PrettyMethod(method);
-  }
-  LOG(INFO) << "Info: " << info;
+void ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
+                                                                   const Method* referrer,
+                                                                   const Method* interface_method,
+                                                                   Object* this_object) {
+  self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
+                           "class '%s' does not implement interface '%s' in call to '%s' from '%s'",
+                           PrettyDescriptor(this_object->GetClass()).c_str(),
+                           PrettyDescriptor(interface_method->GetDeclaringClass()).c_str(),
+                           PrettyMethod(interface_method).c_str(), PrettyMethod(referrer).c_str());
 }
 
-// Return value helper for jobject return types
-extern Object* DecodeJObjectInThread(Thread* thread, jobject obj) {
-  if (thread->IsExceptionPending()) {
-    return NULL;
-  }
-  return thread->DecodeJObject(obj);
+void ThrowNewIllegalAccessErrorField(Thread* self,
+                                     Class* referrer,
+                                     Field* accessed) {
+  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
+                           "Field '%s' is inaccessible to class '%s'",
+                           PrettyField(accessed, false).c_str(),
+                           PrettyDescriptor(referrer).c_str());
 }
 
-extern void* FindNativeMethod(Thread* self) {
-  DCHECK(Thread::Current() == self);
-
-  Method* method = const_cast<Method*>(self->GetCurrentMethod());
-  DCHECK(method != NULL);
-
-  // Lookup symbol address for method, on failure we'll return NULL with an
-  // exception set, otherwise we return the address of the method we found.
-  void* native_code = self->GetJniEnv()->vm->FindCodeForNativeMethod(method);
-  if (native_code == NULL) {
-    DCHECK(self->IsExceptionPending());
-    return NULL;
-  } else {
-    // Register so that future calls don't come here
-    method->RegisterNative(self, native_code);
-    return native_code;
-  }
+void ThrowNewIllegalAccessErrorFinalField(Thread* self,
+                                          const Method* referrer,
+                                          Field* accessed) {
+  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
+                           "Final field '%s' cannot be written to by method '%s'",
+                           PrettyField(accessed, false).c_str(),
+                           PrettyMethod(referrer).c_str());
 }
 
-// Called by generated call to throw an exception
-extern "C" void artDeliverExceptionFromCode(Throwable* exception, Thread* thread, Method** sp) {
-  /*
-   * exception may be NULL, in which case this routine should
-   * throw NPE.  NOTE: this is a convenience for generated code,
-   * which previously did the null check inline and constructed
-   * and threw a NPE if NULL.  This routine responsible for setting
-   * exception_ in thread and delivering the exception.
-   */
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-  if (exception == NULL) {
-    thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
-  } else {
-    thread->SetException(exception);
-  }
-  thread->DeliverException();
+void ThrowNewIllegalAccessErrorMethod(Thread* self,
+                                      Class* referrer,
+                                      Method* accessed) {
+  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
+                           "Method '%s' is inaccessible to class '%s'",
+                           PrettyMethod(accessed).c_str(),
+                           PrettyDescriptor(referrer).c_str());
 }
 
-// Deliver an exception that's pending on thread helping set up a callee save frame on the way
-extern "C" void artDeliverPendingExceptionFromCode(Thread* thread, Method** sp) {
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-  thread->DeliverException();
+void ThrowNullPointerExceptionForFieldAccess(Thread* self,
+                                                           Field* field,
+                                                           bool is_read) {
+  self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
+                           "Attempt to %s field '%s' on a null object reference",
+                           is_read ? "read from" : "write to",
+                           PrettyField(field, true).c_str());
 }
 
-// Called by generated call to throw a NPE exception
-extern "C" void artThrowNullPointerExceptionFromCode(Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
-  Frame fr = self->GetTopOfStack();
-  uintptr_t throw_native_pc = fr.GetReturnPC();
-  fr.Next();
-  Method* throw_method = fr.GetMethod();
-  uint32_t dex_pc = throw_method->ToDexPC(throw_native_pc - 2);
-  const DexFile::CodeItem* code = MethodHelper(throw_method).GetCodeItem();
-  CHECK_LT(dex_pc, code->insns_size_in_code_units_);
-  const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
-  DecodedInstruction dec_insn(instr);
-  switch (instr->Opcode()) {
-    case Instruction::INVOKE_DIRECT:
-    case Instruction::INVOKE_DIRECT_RANGE:
-      ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kDirect);
-      break;
-    case Instruction::INVOKE_VIRTUAL:
-    case Instruction::INVOKE_VIRTUAL_RANGE:
-      ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kVirtual);
-      break;
-    case Instruction::IGET:
-    case Instruction::IGET_WIDE:
-    case Instruction::IGET_OBJECT:
-    case Instruction::IGET_BOOLEAN:
-    case Instruction::IGET_BYTE:
-    case Instruction::IGET_CHAR:
-    case Instruction::IGET_SHORT: {
-      Field* field =
-          Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
-      ThrowNullPointerExceptionForFieldAccess(self, field, true /* read */);
-      break;
-    }
-    case Instruction::IPUT:
-    case Instruction::IPUT_WIDE:
-    case Instruction::IPUT_OBJECT:
-    case Instruction::IPUT_BOOLEAN:
-    case Instruction::IPUT_BYTE:
-    case Instruction::IPUT_CHAR:
-    case Instruction::IPUT_SHORT: {
-      Field* field =
-          Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
-      ThrowNullPointerExceptionForFieldAccess(self, field, false /* write */);
-      break;
-    }
-    case Instruction::AGET:
-    case Instruction::AGET_WIDE:
-    case Instruction::AGET_OBJECT:
-    case Instruction::AGET_BOOLEAN:
-    case Instruction::AGET_BYTE:
-    case Instruction::AGET_CHAR:
-    case Instruction::AGET_SHORT:
-      self->ThrowNewException("Ljava/lang/NullPointerException;",
-                              "Attempt to read from null array");
-      break;
-    case Instruction::APUT:
-    case Instruction::APUT_WIDE:
-    case Instruction::APUT_OBJECT:
-    case Instruction::APUT_BOOLEAN:
-    case Instruction::APUT_BYTE:
-    case Instruction::APUT_CHAR:
-    case Instruction::APUT_SHORT:
-      self->ThrowNewException("Ljava/lang/NullPointerException;",
-                              "Attempt to write to null array");
-      break;
-    default: {
-      const DexFile& dex_file = Runtime::Current()->GetClassLinker()
-          ->FindDexFile(throw_method->GetDeclaringClass()->GetDexCache());
-      std::string message("Null pointer exception during instruction '");
-      message += instr->DumpString(&dex_file);
-      message += "'";
-      self->ThrowNewException("Ljava/lang/NullPointerException;", message.c_str());
-      break;
-    }
-  }
-  self->DeliverException();
+void ThrowNullPointerExceptionForMethodAccess(Thread* self,
+                                              Method* caller,
+                                              uint32_t method_idx,
+                                              InvokeType type) {
+  const DexFile& dex_file =
+      Runtime::Current()->GetClassLinker()->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
+  std::ostringstream type_stream;
+  type_stream << type;
+  self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
+                           "Attempt to invoke %s method '%s' on a null object reference",
+                           type_stream.str().c_str(),
+                           PrettyMethod(method_idx, dex_file, true).c_str());
 }
 
-// Called by generated call to throw an arithmetic divide by zero exception
-extern "C" void artThrowDivZeroFromCode(Thread* thread, Method** sp) {
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-  thread->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
-  thread->DeliverException();
-}
-
-// Called by generated call to throw an arithmetic divide by zero exception
-extern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread, Method** sp) {
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-  thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
-                             "length=%d; index=%d", limit, index);
-  thread->DeliverException();
-}
-
-// Called by the AbstractMethodError stub (not runtime support)
-extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp) {
-#if !defined(ART_USE_LLVM_COMPILER)
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-#endif
-  thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
-                             "abstract method \"%s\"", PrettyMethod(method).c_str());
-#if !defined(ART_USE_LLVM_COMPILER)
-  thread->DeliverException();
-#endif
-}
-
-extern "C" void artThrowStackOverflowFromCode(Method* /*method*/, Thread* thread, Method** sp) {
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-  // Remove extra entry pushed onto second stack during method tracing
-  if (Runtime::Current()->IsMethodTracingActive()) {
-    TraceMethodUnwindFromCode(thread);
-  }
-  thread->SetStackEndForStackOverflow();  // Allow space on the stack for constructor to execute
-  thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;",
-      "stack size %zdkb; default stack size: %zdkb",
-      thread->GetStackSize() / KB, Runtime::Current()->GetDefaultStackSize() / KB);
-  thread->ResetDefaultStackEnd();  // Return to default stack size
-  thread->DeliverException();
-}
-
-static std::string ClassNameFromIndex(Method* method, uint32_t ref,
-                                      verifier::VerifyErrorRefType ref_type, bool access) {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
-
-  uint16_t type_idx = 0;
-  if (ref_type == verifier::VERIFY_ERROR_REF_FIELD) {
-    const DexFile::FieldId& id = dex_file.GetFieldId(ref);
-    type_idx = id.class_idx_;
-  } else if (ref_type == verifier::VERIFY_ERROR_REF_METHOD) {
-    const DexFile::MethodId& id = dex_file.GetMethodId(ref);
-    type_idx = id.class_idx_;
-  } else if (ref_type == verifier::VERIFY_ERROR_REF_CLASS) {
-    type_idx = ref;
-  } else {
-    CHECK(false) << static_cast<int>(ref_type);
-  }
-
-  std::string class_name(PrettyDescriptor(dex_file.StringByTypeIdx(type_idx)));
-  if (!access) {
-    return class_name;
-  }
-
-  std::string result;
-  result += "tried to access class ";
-  result += class_name;
-  result += " from class ";
-  result += PrettyDescriptor(method->GetDeclaringClass());
-  return result;
-}
-
-static std::string FieldNameFromIndex(const Method* method, uint32_t ref,
-                                      verifier::VerifyErrorRefType ref_type, bool access) {
+std::string FieldNameFromIndex(const Method* method, uint32_t ref,
+                               verifier::VerifyErrorRefType ref_type, bool access) {
   CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_FIELD));
 
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -280,8 +128,8 @@
   return result;
 }
 
-static std::string MethodNameFromIndex(const Method* method, uint32_t ref,
-                                       verifier::VerifyErrorRefType ref_type, bool access) {
+std::string MethodNameFromIndex(const Method* method, uint32_t ref,
+                                verifier::VerifyErrorRefType ref_type, bool access) {
   CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_METHOD));
 
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -303,1092 +151,228 @@
   return result;
 }
 
-extern "C" void artThrowVerificationErrorFromCode(int32_t kind, int32_t ref, Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
-  Frame frame = self->GetTopOfStack();  // We need the calling method as context to interpret 'ref'
-  frame.Next();
-  Method* method = frame.GetMethod();
-
-  verifier::VerifyErrorRefType ref_type =
-      static_cast<verifier::VerifyErrorRefType>(kind >> verifier::kVerifyErrorRefTypeShift);
-
-  const char* exception_class = "Ljava/lang/VerifyError;";
-  std::string msg;
-
-  switch (static_cast<verifier::VerifyError>(kind & ~(0xff << verifier::kVerifyErrorRefTypeShift))) {
-  case verifier::VERIFY_ERROR_NO_CLASS:
-    exception_class = "Ljava/lang/NoClassDefFoundError;";
-    msg = ClassNameFromIndex(method, ref, ref_type, false);
-    break;
-  case verifier::VERIFY_ERROR_NO_FIELD:
-    exception_class = "Ljava/lang/NoSuchFieldError;";
-    msg = FieldNameFromIndex(method, ref, ref_type, false);
-    break;
-  case verifier::VERIFY_ERROR_NO_METHOD:
-    exception_class = "Ljava/lang/NoSuchMethodError;";
-    msg = MethodNameFromIndex(method, ref, ref_type, false);
-    break;
-  case verifier::VERIFY_ERROR_ACCESS_CLASS:
-    exception_class = "Ljava/lang/IllegalAccessError;";
-    msg = ClassNameFromIndex(method, ref, ref_type, true);
-    break;
-  case verifier::VERIFY_ERROR_ACCESS_FIELD:
-    exception_class = "Ljava/lang/IllegalAccessError;";
-    msg = FieldNameFromIndex(method, ref, ref_type, true);
-    break;
-  case verifier::VERIFY_ERROR_ACCESS_METHOD:
-    exception_class = "Ljava/lang/IllegalAccessError;";
-    msg = MethodNameFromIndex(method, ref, ref_type, true);
-    break;
-  case verifier::VERIFY_ERROR_CLASS_CHANGE:
-    exception_class = "Ljava/lang/IncompatibleClassChangeError;";
-    msg = ClassNameFromIndex(method, ref, ref_type, false);
-    break;
-  case verifier::VERIFY_ERROR_INSTANTIATION:
-    exception_class = "Ljava/lang/InstantiationError;";
-    msg = ClassNameFromIndex(method, ref, ref_type, false);
-    break;
-  case verifier::VERIFY_ERROR_BAD_CLASS_SOFT:
-  case verifier::VERIFY_ERROR_BAD_CLASS_HARD:
-    // Generic VerifyError; use default exception, no message.
-    break;
-  case verifier::VERIFY_ERROR_NONE:
-    CHECK(false);
-    break;
+// Helper function to allocate array for FILLED_NEW_ARRAY.
+Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
+                                  Thread* self, bool access_check) {
+  if (UNLIKELY(component_count < 0)) {
+    self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
+    return NULL;  // Failure
   }
-  self->ThrowNewException(exception_class, msg.c_str());
-  self->DeliverException();
-}
-
-extern "C" void artThrowInternalErrorFromCode(int32_t errnum, Thread* thread, Method** sp) {
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-  LOG(WARNING) << "TODO: internal error detail message. errnum=" << errnum;
-  thread->ThrowNewExceptionF("Ljava/lang/InternalError;", "errnum=%d", errnum);
-  thread->DeliverException();
-}
-
-extern "C" void artThrowRuntimeExceptionFromCode(int32_t errnum, Thread* thread, Method** sp) {
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-  LOG(WARNING) << "TODO: runtime exception detail message. errnum=" << errnum;
-  thread->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "errnum=%d", errnum);
-  thread->DeliverException();
-}
-
-extern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
-  Frame frame = self->GetTopOfStack();  // We need the calling method as context for the method_idx
-  frame.Next();
-  Method* method = frame.GetMethod();
-  self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
-      MethodNameFromIndex(method, method_idx, verifier::VERIFY_ERROR_REF_METHOD, false).c_str());
-  self->DeliverException();
-}
-
-extern "C" void artThrowNegArraySizeFromCode(int32_t size, Thread* thread, Method** sp) {
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-  LOG(WARNING) << "UNTESTED artThrowNegArraySizeFromCode";
-  thread->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", size);
-  thread->DeliverException();
-}
-
-const void* UnresolvedDirectMethodTrampolineFromCode(Method* called, Method** sp, Thread* thread,
-                                                     Runtime::TrampolineType type) {
-  // TODO: this code is specific to ARM
-  // On entry the stack pointed by sp is:
-  // | argN       |  |
-  // | ...        |  |
-  // | arg4       |  |
-  // | arg3 spill |  |  Caller's frame
-  // | arg2 spill |  |
-  // | arg1 spill |  |
-  // | Method*    | ---
-  // | LR         |
-  // | ...        |    callee saves
-  // | R3         |    arg3
-  // | R2         |    arg2
-  // | R1         |    arg1
-  // | R0         |
-  // | Method*    |  <- sp
-  uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
-  DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
-  Method** caller_sp = reinterpret_cast<Method**>(reinterpret_cast<byte*>(sp) + 48);
-  uintptr_t caller_pc = regs[10];
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
-  // Start new JNI local reference state
-  JNIEnvExt* env = thread->GetJniEnv();
-  ScopedJniEnvLocalRefState env_state(env);
-
-  // Compute details about the called method (avoid GCs)
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  Method* caller = *caller_sp;
-  bool is_static;
-  bool is_virtual;
-  uint32_t dex_method_idx;
-  const char* shorty;
-  uint32_t shorty_len;
-  if (type == Runtime::kUnknownMethod) {
-    DCHECK(called->IsRuntimeMethod());
-    // less two as return address may span into next dex instruction
-    uint32_t dex_pc = caller->ToDexPC(caller_pc - 2);
-    const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
-    CHECK_LT(dex_pc, code->insns_size_in_code_units_);
-    const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
-    Instruction::Code instr_code = instr->Opcode();
-    is_static = (instr_code == Instruction::INVOKE_STATIC) ||
-                (instr_code == Instruction::INVOKE_STATIC_RANGE);
-    is_virtual = (instr_code == Instruction::INVOKE_VIRTUAL) ||
-                 (instr_code == Instruction::INVOKE_VIRTUAL_RANGE) ||
-                 (instr_code == Instruction::INVOKE_SUPER) ||
-                 (instr_code == Instruction::INVOKE_SUPER_RANGE);
-    DCHECK(is_static || is_virtual || (instr_code == Instruction::INVOKE_DIRECT) ||
-           (instr_code == Instruction::INVOKE_DIRECT_RANGE));
-    DecodedInstruction dec_insn(instr);
-    dex_method_idx = dec_insn.vB;
-    shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
-  } else {
-    DCHECK(!called->IsRuntimeMethod());
-    is_static = type == Runtime::kStaticMethod;
-    is_virtual = false;
-    dex_method_idx = called->GetDexMethodIndex();
-    MethodHelper mh(called);
-    shorty = mh.GetShorty();
-    shorty_len = mh.GetShortyLength();
-  }
-  // Discover shorty (avoid GCs)
-  size_t args_in_regs = 0;
-  for (size_t i = 1; i < shorty_len; i++) {
-    char c = shorty[i];
-    args_in_regs = args_in_regs + (c == 'J' || c == 'D' ? 2 : 1);
-    if (args_in_regs > 3) {
-      args_in_regs = 3;
-      break;
+  Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+  if (UNLIKELY(klass == NULL)) {  // Not in dex cache so try to resolve
+    klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
+    if (klass == NULL) {  // Error
+      DCHECK(Thread::Current()->IsExceptionPending());
+      return NULL;  // Failure
     }
   }
-  // Place into local references incoming arguments from the caller's register arguments
-  size_t cur_arg = 1;   // skip method_idx in R0, first arg is in R1
-  if (!is_static) {
-    Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
-    cur_arg++;
-    if (args_in_regs < 3) {
-      // If we thought we had fewer than 3 arguments in registers, account for the receiver
-      args_in_regs++;
-    }
-    AddLocalReference<jobject>(env, obj);
-  }
-  size_t shorty_index = 1;  // skip return value
-  // Iterate while arguments and arguments in registers (less 1 from cur_arg which is offset to skip
-  // R0)
-  while ((cur_arg - 1) < args_in_regs && shorty_index < shorty_len) {
-    char c = shorty[shorty_index];
-    shorty_index++;
-    if (c == 'L') {
-      Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
-      AddLocalReference<jobject>(env, obj);
-    }
-    cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
-  }
-  // Place into local references incoming arguments from the caller's stack arguments
-  cur_arg += 11;  // skip LR, Method* and spills for R1 to R3 and callee saves
-  while (shorty_index < shorty_len) {
-    char c = shorty[shorty_index];
-    shorty_index++;
-    if (c == 'L') {
-      Object* obj = reinterpret_cast<Object*>(regs[cur_arg]);
-      AddLocalReference<jobject>(env, obj);
-    }
-    cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
-  }
-  // Resolve method filling in dex cache
-  if (type == Runtime::kUnknownMethod) {
-    called = linker->ResolveMethod(dex_method_idx, caller, !is_virtual);
-  }
-  const void* code = NULL;
-  if (LIKELY(!thread->IsExceptionPending())) {
-    if (LIKELY(called->IsDirect() == !is_virtual)) {
-      // Ensure that the called method's class is initialized.
-      Class* called_class = called->GetDeclaringClass();
-      linker->EnsureInitialized(called_class, true);
-      if (LIKELY(called_class->IsInitialized())) {
-        code = called->GetCode();
-      } else if (called_class->IsInitializing()) {
-        if (is_static) {
-          // Class is still initializing, go to oat and grab code (trampoline must be left in place
-          // until class is initialized to stop races between threads).
-          code = linker->GetOatCodeFor(called);
-        } else {
-          // No trampoline for non-static methods.
-          code = called->GetCode();
-        }
-      } else {
-        DCHECK(called_class->IsErroneous());
-      }
+  if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
+    if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
+      Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
+                                            "Bad filled array request for type %s",
+                                            PrettyDescriptor(klass).c_str());
     } else {
-      // Direct method has been made virtual
-      thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
-                                 "Expected direct method but found virtual: %s",
-                                 PrettyMethod(called, true).c_str());
+      Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;",
+                                            "Found type %s; filled-new-array not implemented for anything but \'int\'",
+                                            PrettyDescriptor(klass).c_str());
     }
-  }
-  if (UNLIKELY(code == NULL)) {
-    // Something went wrong in ResolveMethod or EnsureInitialized,
-    // go into deliver exception with the pending exception in r0
-    code = reinterpret_cast<void*>(art_deliver_exception_from_code);
-    regs[0] = reinterpret_cast<uintptr_t>(thread->GetException());
-    thread->ClearException();
+    return NULL;  // Failure
   } else {
-    // Expect class to at least be initializing.
-    DCHECK(called->GetDeclaringClass()->IsInitializing());
-    // Don't want infinite recursion.
-    DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
-    // Set up entry into main method
-    regs[0] = reinterpret_cast<uintptr_t>(called);
-  }
-  return code;
-}
-
-static void WorkAroundJniBugsForJobject(intptr_t* arg_ptr) {
-  intptr_t value = *arg_ptr;
-  Object** value_as_jni_rep = reinterpret_cast<Object**>(value);
-  Object* value_as_work_around_rep = value_as_jni_rep != NULL ? *value_as_jni_rep : NULL;
-  CHECK(Runtime::Current()->GetHeap()->IsHeapAddress(value_as_work_around_rep)) << value_as_work_around_rep;
-  *arg_ptr = reinterpret_cast<intptr_t>(value_as_work_around_rep);
-}
-
-extern "C" const void* artWorkAroundAppJniBugs(Thread* self, intptr_t* sp) {
-  DCHECK(Thread::Current() == self);
-  // TODO: this code is specific to ARM
-  // On entry the stack pointed by sp is:
-  // | arg3   | <- Calling JNI method's frame (and extra bit for out args)
-  // | LR     |
-  // | R3     |    arg2
-  // | R2     |    arg1
-  // | R1     |    jclass/jobject
-  // | R0     |    JNIEnv
-  // | unused |
-  // | unused |
-  // | unused | <- sp
-  Method* jni_method = self->GetTopOfStack().GetMethod();
-  DCHECK(jni_method->IsNative()) << PrettyMethod(jni_method);
-  intptr_t* arg_ptr = sp + 4;  // pointer to r1 on stack
-  // Fix up this/jclass argument
-  WorkAroundJniBugsForJobject(arg_ptr);
-  arg_ptr++;
-  // Fix up jobject arguments
-  MethodHelper mh(jni_method);
-  int reg_num = 2;  // Current register being processed, -1 for stack arguments.
-  for (uint32_t i = 1; i < mh.GetShortyLength(); i++) {
-    char shorty_char = mh.GetShorty()[i];
-    if (shorty_char == 'L') {
-      WorkAroundJniBugsForJobject(arg_ptr);
+    if (access_check) {
+      Class* referrer = method->GetDeclaringClass();
+      if (UNLIKELY(!referrer->CanAccess(klass))) {
+        ThrowNewIllegalAccessErrorClass(self, referrer, klass);
+        return NULL;  // Failure
+      }
     }
-    if (shorty_char == 'J' || shorty_char == 'D') {
-      if (reg_num == 2) {
-        arg_ptr = sp + 8;  // skip to out arguments
-        reg_num = -1;
-      } else if (reg_num == 3) {
-        arg_ptr = sp + 10;  // skip to out arguments plus 2 slots as long must be aligned
-        reg_num = -1;
+    DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
+    return Array::Alloc(klass, component_count);
+  }
+}
+
+// Slow path field resolution and declaring class initialization
+Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
+                         bool is_static, bool is_primitive, bool is_set, size_t expected_size) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
+  if (UNLIKELY(resolved_field == NULL)) {
+    DCHECK(self->IsExceptionPending());  // Throw exception and unwind
+    return NULL;  // failure
+  } else {
+    Class* fields_class = resolved_field->GetDeclaringClass();
+    Class* referring_class = referrer->GetDeclaringClass();
+    if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
+      ThrowNewIllegalAccessErrorClass(self, referring_class, fields_class);
+      return NULL;  // failure
+    } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
+                                                          resolved_field->GetAccessFlags()))) {
+      ThrowNewIllegalAccessErrorField(self, referring_class, resolved_field);
+      return NULL;  // failure
+    } else if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
+      ThrowNewIllegalAccessErrorFinalField(self, referrer, resolved_field);
+      return NULL;  // failure
+    } else {
+      FieldHelper fh(resolved_field);
+      if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
+                   fh.FieldSize() != expected_size)) {
+        self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
+                                 "Attempted read of %zd-bit %s on field '%s'",
+                                 expected_size * (32 / sizeof(int32_t)),
+                                 is_primitive ? "primitive" : "non-primitive",
+                                 PrettyField(resolved_field, true).c_str());
+        return NULL;  // failure
+      } else if (!is_static) {
+        // instance fields must be being accessed on an initialized class
+        return resolved_field;
       } else {
-        DCHECK(reg_num == -1);
-        if ((reinterpret_cast<intptr_t>(arg_ptr) & 7) == 4) {
-          arg_ptr += 3;  // unaligned, pad and move through stack arguments
+        // If the class is already initializing, we must be inside <clinit>, or
+        // we'd still be waiting for the lock.
+        if (fields_class->IsInitializing()) {
+          return resolved_field;
+        } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true)) {
+          return resolved_field;
         } else {
-          arg_ptr += 2;  // aligned, move through stack arguments
+          DCHECK(self->IsExceptionPending());  // Throw exception and unwind
+          return NULL;  // failure
         }
       }
-    } else {
-      if (reg_num == 2) {
-        arg_ptr++; // move through register arguments
-        reg_num++;
-      } else if (reg_num == 3) {
-        arg_ptr = sp + 8;  // skip to outgoing stack arguments
-        reg_num = -1;
+    }
+  }
+}
+
+// Slow path method resolution
+Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
+                           Thread* self, bool access_check, InvokeType type) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  bool is_direct = type == kStatic || type == kDirect;
+  Method* resolved_method = class_linker->ResolveMethod(method_idx, referrer, is_direct);
+  if (UNLIKELY(resolved_method == NULL)) {
+    DCHECK(self->IsExceptionPending());  // Throw exception and unwind
+    return NULL;  // failure
+  } else {
+    if (!access_check) {
+      if (is_direct) {
+        return resolved_method;
+      } else if (type == kInterface) {
+        Method* interface_method =
+            this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
+        if (UNLIKELY(interface_method == NULL)) {
+          ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
+                                                                        resolved_method,
+                                                                        this_object);
+          return NULL;  // failure
+        } else {
+          return interface_method;
+        }
       } else {
-        DCHECK(reg_num == -1);
-        arg_ptr++;  // move through stack arguments
+        ObjectArray<Method>* vtable;
+        uint16_t vtable_index = resolved_method->GetMethodIndex();
+        if (type == kSuper) {
+          vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
+        } else {
+          vtable = this_object->GetClass()->GetVTable();
+        }
+        // TODO: eliminate bounds check?
+        return vtable->Get(vtable_index);
+      }
+    } else {
+      Class* methods_class = resolved_method->GetDeclaringClass();
+      Class* referring_class = referrer->GetDeclaringClass();
+      if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
+                   !referring_class->CanAccessMember(methods_class,
+                                                     resolved_method->GetAccessFlags()))) {
+        // The referring class can't access the resolved method, this may occur as a result of a
+        // protected method being made public by implementing an interface that re-declares the
+        // method public. Resort to the dex file to determine the correct class for the access check
+        const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
+        methods_class = class_linker->ResolveType(dex_file,
+                                                  dex_file.GetMethodId(method_idx).class_idx_,
+                                                  referring_class);
+        if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
+          ThrowNewIllegalAccessErrorClassForMethodDispatch(self, referring_class, methods_class,
+                                                           referrer, resolved_method, type);
+          return NULL;  // failure
+        } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
+                                                              resolved_method->GetAccessFlags()))) {
+          ThrowNewIllegalAccessErrorMethod(self, referring_class, resolved_method);
+          return NULL;  // failure
+        }
+      }
+      if (is_direct) {
+        return resolved_method;
+      } else if (type == kInterface) {
+        Method* interface_method =
+            this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
+        if (UNLIKELY(interface_method == NULL)) {
+          ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
+                                                                        resolved_method,
+                                                                        this_object);
+          return NULL;  // failure
+        } else {
+          return interface_method;
+        }
+      } else {
+        ObjectArray<Method>* vtable;
+        uint16_t vtable_index = resolved_method->GetMethodIndex();
+        if (type == kSuper) {
+          Class* super_class = referring_class->GetSuperClass();
+          if (LIKELY(super_class != NULL)) {
+            vtable = referring_class->GetSuperClass()->GetVTable();
+          } else {
+            vtable = NULL;
+          }
+        } else {
+          vtable = this_object->GetClass()->GetVTable();
+        }
+        if (LIKELY(vtable != NULL &&
+                   vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
+          return vtable->GetWithoutChecks(vtable_index);
+        } else {
+          // Behavior to agree with that of the verifier
+          self->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
+                                   "attempt to invoke %s method '%s' from '%s'"
+                                   " using incorrect form of method dispatch",
+                                   (type == kSuper ? "super class" : "virtual"),
+                                   PrettyMethod(resolved_method).c_str(),
+                                   PrettyMethod(referrer).c_str());
+          return NULL;  // failure
+        }
       }
     }
   }
-  // Load expected destination, see Method::RegisterNative
-  const void* code = reinterpret_cast<const void*>(jni_method->GetGcMapRaw());
-  if (UNLIKELY(code == NULL)) {
-    code = Runtime::Current()->GetJniDlsymLookupStub()->GetData();
-    jni_method->RegisterNative(self, code);
-  }
-  return code;
 }
 
-
-extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const Method* referrer,
-                                           Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int32_t));
-  if (LIKELY(field != NULL)) {
-    return field->Get32(NULL);
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, true, true, false, sizeof(int32_t));
-  if (LIKELY(field != NULL)) {
-    return field->Get32(NULL);
-  }
-  return 0;  // Will throw exception by checking with Thread::Current
-}
-
-extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const Method* referrer,
-                                           Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int64_t));
-  if (LIKELY(field != NULL)) {
-    return field->Get64(NULL);
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, true, true, false, sizeof(int64_t));
-  if (LIKELY(field != NULL)) {
-    return field->Get64(NULL);
-  }
-  return 0;  // Will throw exception by checking with Thread::Current
-}
-
-extern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
-                                           Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
-  if (LIKELY(field != NULL)) {
-    return field->GetObj(NULL);
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, true, false, false, sizeof(Object*));
-  if (LIKELY(field != NULL)) {
-    return field->GetObj(NULL);
-  }
-  return NULL;  // Will throw exception by checking with Thread::Current
-}
-
-extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, Object* obj,
-                                             const Method* referrer, Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int32_t));
-  if (LIKELY(field != NULL && obj != NULL)) {
-    return field->Get32(obj);
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, false, true, false, sizeof(int32_t));
-  if (LIKELY(field != NULL)) {
-    if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, true);
-    } else {
-      return field->Get32(obj);
-    }
-  }
-  return 0;  // Will throw exception by checking with Thread::Current
-}
-
-extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, Object* obj,
-                                             const Method* referrer, Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, true, false, sizeof(int64_t));
-  if (LIKELY(field != NULL && obj != NULL)) {
-    return field->Get64(obj);
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, false, true, false, sizeof(int64_t));
-  if (LIKELY(field != NULL)) {
-    if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, true);
-    } else {
-      return field->Get64(obj);
-    }
-  }
-  return 0;  // Will throw exception by checking with Thread::Current
-}
-
-extern "C" Object* artGetObjInstanceFromCode(uint32_t field_idx, Object* obj,
-                                              const Method* referrer, Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, false, false, sizeof(Object*));
-  if (LIKELY(field != NULL && obj != NULL)) {
-    return field->GetObj(obj);
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, false, false, false, sizeof(Object*));
-  if (LIKELY(field != NULL)) {
-    if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, true);
-    } else {
-      return field->GetObj(obj);
-    }
-  }
-  return NULL;  // Will throw exception by checking with Thread::Current
-}
-
-extern "C" int artSet32StaticFromCode(uint32_t field_idx, uint32_t new_value,
-                                      const Method* referrer, Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int32_t));
-  if (LIKELY(field != NULL)) {
-    field->Set32(NULL, new_value);
-    return 0;  // success
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, true, true, true, sizeof(int32_t));
-  if (LIKELY(field != NULL)) {
-    field->Set32(NULL, new_value);
-    return 0;  // success
-  }
-  return -1;  // failure
-}
-
-extern "C" int artSet64StaticFromCode(uint32_t field_idx, const Method* referrer,
-                                      uint64_t new_value, Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int64_t));
-  if (LIKELY(field != NULL)) {
-    field->Set64(NULL, new_value);
-    return 0;  // success
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, true, true, true, sizeof(int64_t));
-  if (LIKELY(field != NULL)) {
-    field->Set64(NULL, new_value);
-    return 0;  // success
-  }
-  return -1;  // failure
-}
-
-extern "C" int artSetObjStaticFromCode(uint32_t field_idx, Object* new_value,
-                                       const Method* referrer, Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
-  if (LIKELY(field != NULL)) {
-    if (LIKELY(!FieldHelper(field).IsPrimitiveType())) {
-      field->SetObj(NULL, new_value);
-      return 0;  // success
-    }
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, true, false, true, sizeof(Object*));
-  if (LIKELY(field != NULL)) {
-    field->SetObj(NULL, new_value);
-    return 0;  // success
-  }
-  return -1;  // failure
-}
-
-extern "C" int artSet32InstanceFromCode(uint32_t field_idx, Object* obj, uint32_t new_value,
-                                        const Method* referrer, Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int32_t));
-  if (LIKELY(field != NULL && obj != NULL)) {
-    field->Set32(obj, new_value);
-    return 0;  // success
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, false, true, true, sizeof(int32_t));
-  if (LIKELY(field != NULL)) {
-    if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, false);
-    } else {
-      field->Set32(obj, new_value);
-      return 0;  // success
-    }
-  }
-  return -1;  // failure
-}
-
-extern "C" int artSet64InstanceFromCode(uint32_t field_idx, Object* obj, uint64_t new_value,
-                                        Thread* self, Method** sp) {
-  Method* callee_save = Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsOnly);
-  Method* referrer = sp[callee_save->GetFrameSizeInBytes() / sizeof(Method*)];
-  Field* field = FindFieldFast(field_idx, referrer, true, true, sizeof(int64_t));
-  if (LIKELY(field != NULL  && obj != NULL)) {
-    field->Set64(obj, new_value);
-    return 0;  // success
-  }
-  *sp = callee_save;
-  self->SetTopOfStack(sp, 0);
-  field = FindFieldFromCode(field_idx, referrer, self, false, true, true, sizeof(int64_t));
-  if (LIKELY(field != NULL)) {
-    if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, false);
-    } else {
-      field->Set64(obj, new_value);
-      return 0;  // success
-    }
-  }
-  return -1;  // failure
-}
-
-extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, Object* obj, Object* new_value,
-                                         const Method* referrer, Thread* self, Method** sp) {
-  Field* field = FindFieldFast(field_idx, referrer, false, true, sizeof(Object*));
-  if (LIKELY(field != NULL && obj != NULL)) {
-    field->SetObj(obj, new_value);
-    return 0;  // success
-  }
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  field = FindFieldFromCode(field_idx, referrer, self, false, false, true, sizeof(Object*));
-  if (LIKELY(field != NULL)) {
-    if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, false);
-    } else {
-      field->SetObj(obj, new_value);
-      return 0;  // success
-    }
-  }
-  return -1;  // failure
-}
-
-extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method,
-                                          Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return AllocObjectFromCode(type_idx, method, self, false);
-}
-
-extern "C" Object* artAllocObjectFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
-                                                         Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return AllocObjectFromCode(type_idx, method, self, true);
-}
-
-extern "C" Array* artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
-                                        Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return AllocArrayFromCode(type_idx, method, component_count, self, false);
-}
-
-extern "C" Array* artAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
-                                                       int32_t component_count,
-                                                       Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return AllocArrayFromCode(type_idx, method, component_count, self, true);
-}
-
-extern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method,
-                                               int32_t component_count, Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return CheckAndAllocArrayFromCode(type_idx, method, component_count, self, false);
-}
-
-extern "C" Array* artCheckAndAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
-                                                               int32_t component_count,
-                                                               Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return CheckAndAllocArrayFromCode(type_idx, method, component_count, self, true);
-}
-
-// Assignable test for code, won't throw.  Null and equality tests already performed
-uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class) {
-  DCHECK(klass != NULL);
-  DCHECK(ref_class != NULL);
-  return klass->IsAssignableFrom(ref_class) ? 1 : 0;
-}
-
-// Check whether it is safe to cast one class to the other, throw exception and return -1 on failure
-extern "C" int artCheckCastFromCode(const Class* a, const Class* b, Thread* self, Method** sp) {
-  DCHECK(a->IsClass()) << PrettyClass(a);
-  DCHECK(b->IsClass()) << PrettyClass(b);
-  if (LIKELY(b->IsAssignableFrom(a))) {
-    return 0;  // Success
-  } else {
-    FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
-        "%s cannot be cast to %s",
-        PrettyDescriptor(a).c_str(),
-        PrettyDescriptor(b).c_str());
-    return -1;  // Failure
-  }
-}
-
-// Tests whether 'element' can be assigned into an array of type 'array_class'.
-// Returns 0 on success and -1 if an exception is pending.
-extern "C" int artCanPutArrayElementFromCode(const Object* element, const Class* array_class,
-                                             Thread* self, Method** sp) {
-  DCHECK(array_class != NULL);
-  // element can't be NULL as we catch this is screened in runtime_support
-  Class* element_class = element->GetClass();
-  Class* component_type = array_class->GetComponentType();
-  if (LIKELY(component_type->IsAssignableFrom(element_class))) {
-    return 0;  // Success
-  } else {
-    FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
-        "%s cannot be stored in an array of type %s",
-        PrettyDescriptor(element_class).c_str(),
-        PrettyDescriptor(array_class).c_str());
-    return -1;  // Failure
-  }
-}
-
-extern "C" Class* artInitializeStaticStorageFromCode(uint32_t type_idx, const Method* referrer,
-                                                     Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return ResolveVerifyAndClinit(type_idx, referrer, self, true, true);
-}
-
-extern "C" Class* artInitializeTypeFromCode(uint32_t type_idx, const Method* referrer, Thread* self,
-                                            Method** sp) {
-  // Called when method->dex_cache_resolved_types_[] misses
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return ResolveVerifyAndClinit(type_idx, referrer, self, false, false);
-}
-
-extern "C" Class* artInitializeTypeAndVerifyAccessFromCode(uint32_t type_idx,
-                                                           const Method* referrer, Thread* self,
-                                                           Method** sp) {
-  // Called when caller isn't guaranteed to have access to a type and the dex cache may be
-  // unpopulated
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return ResolveVerifyAndClinit(type_idx, referrer, self, false, true);
-}
-
-extern "C" String* artResolveStringFromCode(Method* referrer, int32_t string_idx,
-                                            Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return ResolveStringFromCode(referrer, string_idx);
-}
-
-extern "C" int artUnlockObjectFromCode(Object* obj, Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  DCHECK(obj != NULL);  // Assumed to have been checked before entry
-  // MonitorExit may throw exception
-  return obj->MonitorExit(self) ? 0 /* Success */ : -1 /* Failure */;
-}
-
-extern "C" void artLockObjectFromCode(Object* obj, Thread* thread, Method** sp) {
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly);
-  DCHECK(obj != NULL);        // Assumed to have been checked before entry
-  obj->MonitorEnter(thread);  // May block
-  DCHECK(thread->HoldsLock(obj));
-  // Only possible exception is NPE and is handled before entry
-  DCHECK(!thread->IsExceptionPending());
-}
-
-void CheckSuspendFromCode(Thread* thread) {
-  // Called when thread->suspend_count_ != 0
-  Runtime::Current()->GetThreadList()->FullSuspendCheck(thread);
-}
-
-extern "C" void artTestSuspendFromCode(Thread* thread, Method** sp) {
-  // Called when suspend count check value is 0 and thread->suspend_count_ != 0
-  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsOnly);
-  Runtime::Current()->GetThreadList()->FullSuspendCheck(thread);
-}
-
-/*
- * Fill the array with predefined constant values, throwing exceptions if the array is null or
- * not of sufficient length.
- *
- * NOTE: When dealing with a raw dex file, the data to be copied uses
- * little-endian ordering.  Require that oat2dex do any required swapping
- * so this routine can get by with a memcpy().
- *
- * Format of the data:
- *  ushort ident = 0x0300   magic value
- *  ushort width            width of each element in the table
- *  uint   size             number of elements in the table
- *  ubyte  data[size*width] table of data values (may contain a single-byte
- *                          padding at the end)
- */
-extern "C" int artHandleFillArrayDataFromCode(Array* array, const uint16_t* table,
-                                              Thread* self, Method** sp) {
-  FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  DCHECK_EQ(table[0], 0x0300);
-  if (UNLIKELY(array == NULL)) {
-    Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
-        "null array in fill array");
-    return -1;  // Error
-  }
-  DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
-  uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16);
-  if (UNLIKELY(static_cast<int32_t>(size) > array->GetLength())) {
-    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
-        "failed array fill. length=%d; index=%d", array->GetLength(), size);
-    return -1;  // Error
-  }
-  uint16_t width = table[1];
-  uint32_t size_in_bytes = size * width;
-  memcpy((char*)array + Array::DataOffset(width).Int32Value(), (char*)&table[4], size_in_bytes);
-  return 0;  // Success
-}
-
-static uint64_t artInvokeCommon(uint32_t method_idx, Object* this_object, Method* caller_method,
-                                Thread* self, Method** sp, bool access_check, InvokeType type) {
-  Method* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
-  if (UNLIKELY(method == NULL)) {
-    FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
-    if (UNLIKELY(this_object == NULL && type != kDirect && type != kStatic)) {
-      ThrowNullPointerExceptionForMethodAccess(self, caller_method, method_idx, type);
-      return 0;  // failure
-    }
-    method = FindMethodFromCode(method_idx, this_object, caller_method, self, access_check, type);
-    if (UNLIKELY(method == NULL)) {
-      CHECK(self->IsExceptionPending());
-      return 0;  // failure
-    }
-  }
-  DCHECK(!self->IsExceptionPending());
-  const void* code = method->GetCode();
-
-  // When we return, the caller will branch to this address, so it had better not be 0!
-  CHECK(code != NULL) << PrettyMethod(method);
-
-  uint32_t method_uint = reinterpret_cast<uint32_t>(method);
-  uint64_t code_uint = reinterpret_cast<uint32_t>(code);
-  uint64_t result = ((code_uint << 32) | method_uint);
-  return result;
-}
-
-// See comments in runtime_support_asm.S
-extern "C" uint64_t artInvokeInterfaceTrampoline(uint32_t method_idx, Object* this_object,
-                                                 Method* caller_method, Thread* self,
-                                                 Method** sp) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, false, kInterface);
-}
-
-extern "C" uint64_t artInvokeInterfaceTrampolineWithAccessCheck(uint32_t method_idx,
-                                                                Object* this_object,
-                                                                Method* caller_method, Thread* self,
-                                                                Method** sp) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kInterface);
-}
-
-
-extern "C" uint64_t artInvokeDirectTrampolineWithAccessCheck(uint32_t method_idx,
-                                                             Object* this_object,
-                                                             Method* caller_method, Thread* self,
-                                                             Method** sp) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kDirect);
-}
-
-extern "C" uint64_t artInvokeStaticTrampolineWithAccessCheck(uint32_t method_idx,
-                                                            Object* this_object,
-                                                            Method* caller_method, Thread* self,
-                                                            Method** sp) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kStatic);
-}
-
-extern "C" uint64_t artInvokeSuperTrampolineWithAccessCheck(uint32_t method_idx,
-                                                            Object* this_object,
-                                                            Method* caller_method, Thread* self,
-                                                            Method** sp) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kSuper);
-}
-
-extern "C" uint64_t artInvokeVirtualTrampolineWithAccessCheck(uint32_t method_idx,
-                                                              Object* this_object,
-                                                              Method* caller_method, Thread* self,
-                                                              Method** sp) {
-  return artInvokeCommon(method_idx, this_object, caller_method, self, sp, true, kVirtual);
-}
-
-static void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception) {
-  ScopedLocalRef<jclass> jlr_UTE_class(env,
-      env->FindClass("java/lang/reflect/UndeclaredThrowableException"));
-  if (jlr_UTE_class.get() == NULL) {
-    LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
-  } else {
-    jmethodID jlre_UTE_constructor = env->GetMethodID(jlr_UTE_class.get(), "<init>",
-                                                      "(Ljava/lang/Throwable;)V");
-    jthrowable jexception = AddLocalReference<jthrowable>(env, exception);
-    ScopedLocalRef<jthrowable> jlr_UTE(env,
-        reinterpret_cast<jthrowable>(env->NewObject(jlr_UTE_class.get(), jlre_UTE_constructor,
-                                                    jexception)));
-    int rc = env->Throw(jlr_UTE.get());
-    if (rc != JNI_OK) {
-      LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
-    }
-  }
-  CHECK(self->IsExceptionPending());
-}
-
-// Handler for invocation on proxy methods. On entry a frame will exist for the proxy object method
-// which is responsible for recording callee save registers. We explicitly handlerize incoming
-// reference arguments (so they survive GC) and create a boxed argument array. Finally we invoke
-// the invocation handler which is a field within the proxy object receiver.
-extern "C" void artProxyInvokeHandler(Method* proxy_method, Object* receiver,
-                                      Thread* self, byte* stack_args) {
-  // Register the top of the managed stack
-  Method** proxy_sp = reinterpret_cast<Method**>(stack_args - 12);
-  DCHECK_EQ(*proxy_sp, proxy_method);
-  self->SetTopOfStack(proxy_sp, 0);
-  // TODO: ARM specific
-  DCHECK_EQ(proxy_method->GetFrameSizeInBytes(), 48u);
-  // Start new JNI local reference state
-  JNIEnvExt* env = self->GetJniEnv();
-  ScopedJniEnvLocalRefState env_state(env);
-  // Create local ref. copies of proxy method and the receiver
-  jobject rcvr_jobj = AddLocalReference<jobject>(env, receiver);
-  jobject proxy_method_jobj = AddLocalReference<jobject>(env, proxy_method);
-
-  // Placing into local references incoming arguments from the caller's register arguments,
-  // replacing original Object* with jobject
-  MethodHelper proxy_mh(proxy_method);
-  const size_t num_params = proxy_mh.NumArgs();
-  size_t args_in_regs = 0;
-  for (size_t i = 1; i < num_params; i++) {  // skip receiver
-    args_in_regs = args_in_regs + (proxy_mh.IsParamALongOrDouble(i) ? 2 : 1);
-    if (args_in_regs > 2) {
-      args_in_regs = 2;
-      break;
-    }
-  }
-  size_t cur_arg = 0;  // current stack location to read
-  size_t param_index = 1;  // skip receiver
-  while (cur_arg < args_in_regs && param_index < num_params) {
-    if (proxy_mh.IsParamAReference(param_index)) {
-      Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize));
-      jobject jobj = AddLocalReference<jobject>(env, obj);
-      *reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj;
-    }
-    cur_arg = cur_arg + (proxy_mh.IsParamALongOrDouble(param_index) ? 2 : 1);
-    param_index++;
-  }
-  // Placing into local references incoming arguments from the caller's stack arguments
-  cur_arg += 11;  // skip callee saves, LR, Method* and out arg spills for R1 to R3
-  while (param_index < num_params) {
-    if (proxy_mh.IsParamAReference(param_index)) {
-      Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize));
-      jobject jobj = AddLocalReference<jobject>(env, obj);
-      *reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj;
-    }
-    cur_arg = cur_arg + (proxy_mh.IsParamALongOrDouble(param_index) ? 2 : 1);
-    param_index++;
-  }
-  // Set up arguments array and place in local IRT during boxing (which may allocate/GC)
-  jvalue args_jobj[3];
-  args_jobj[0].l = rcvr_jobj;
-  args_jobj[1].l = proxy_method_jobj;
-  // Args array, if no arguments then NULL (don't include receiver in argument count)
-  args_jobj[2].l = NULL;
-  ObjectArray<Object>* args = NULL;
-  if ((num_params - 1) > 0) {
-    args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(num_params - 1);
-    if (args == NULL) {
-      CHECK(self->IsExceptionPending());
-      return;
-    }
-    args_jobj[2].l = AddLocalReference<jobjectArray>(env, args);
-  }
-  // Convert proxy method into expected interface method
-  Method* interface_method = proxy_method->FindOverriddenMethod();
-  DCHECK(interface_method != NULL);
-  DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
-  args_jobj[1].l = AddLocalReference<jobject>(env, interface_method);
-  // Box arguments
-  cur_arg = 0;  // reset stack location to read to start
-  // reset index, will index into param type array which doesn't include the receiver
-  param_index = 0;
-  ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes();
-  if (param_types == NULL) {
+Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
+                               bool can_run_clinit, bool verify_access) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Class* klass = class_linker->ResolveType(type_idx, referrer);
+  if (UNLIKELY(klass == NULL)) {
     CHECK(self->IsExceptionPending());
-    return;
+    return NULL;  // Failure - Indicate to caller to deliver exception
   }
-  // Check number of parameter types agrees with number from the Method - less 1 for the receiver.
-  DCHECK_EQ(static_cast<size_t>(param_types->GetLength()), num_params - 1);
-  while (cur_arg < args_in_regs && param_index < (num_params - 1)) {
-    Class* param_type = param_types->Get(param_index);
-    Object* obj;
-    if (!param_type->IsPrimitive()) {
-      obj = self->DecodeJObject(*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)));
-    } else {
-      JValue val = *reinterpret_cast<JValue*>(stack_args + (cur_arg * kPointerSize));
-      if (cur_arg == 1 && (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble())) {
-        // long/double split over regs and stack, mask in high half from stack arguments
-        uint64_t high_half = *reinterpret_cast<uint32_t*>(stack_args + (13 * kPointerSize));
-        val.j = (val.j & 0xffffffffULL) | (high_half << 32);
-      }
-      BoxPrimitive(param_type->GetPrimitiveType(), val);
-      if (self->IsExceptionPending()) {
-        return;
-      }
-      obj = val.l;
-    }
-    args->Set(param_index, obj);
-    cur_arg = cur_arg + (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble() ? 2 : 1);
-    param_index++;
+  // Perform access check if necessary.
+  Class* referring_class = referrer->GetDeclaringClass();
+  if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
+    ThrowNewIllegalAccessErrorClass(self, referring_class, klass);
+    return NULL;  // Failure - Indicate to caller to deliver exception
   }
-  // Placing into local references incoming arguments from the caller's stack arguments
-  cur_arg += 11;  // skip callee saves, LR, Method* and out arg spills for R1 to R3
-  while (param_index < (num_params - 1)) {
-    Class* param_type = param_types->Get(param_index);
-    Object* obj;
-    if (!param_type->IsPrimitive()) {
-      obj = self->DecodeJObject(*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)));
-    } else {
-      JValue val = *reinterpret_cast<JValue*>(stack_args + (cur_arg * kPointerSize));
-      BoxPrimitive(param_type->GetPrimitiveType(), val);
-      if (self->IsExceptionPending()) {
-        return;
-      }
-      obj = val.l;
-    }
-    args->Set(param_index, obj);
-    cur_arg = cur_arg + (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble() ? 2 : 1);
-    param_index++;
+  // If we're just implementing const-class, we shouldn't call <clinit>.
+  if (!can_run_clinit) {
+    return klass;
   }
-  // Get the InvocationHandler method and the field that holds it within the Proxy object
-  static jmethodID inv_hand_invoke_mid = NULL;
-  static jfieldID proxy_inv_hand_fid = NULL;
-  if (proxy_inv_hand_fid == NULL) {
-    ScopedLocalRef<jclass> proxy(env, env->FindClass("java/lang/reflect/Proxy"));
-    proxy_inv_hand_fid = env->GetFieldID(proxy.get(), "h", "Ljava/lang/reflect/InvocationHandler;");
-    ScopedLocalRef<jclass> inv_hand_class(env, env->FindClass("java/lang/reflect/InvocationHandler"));
-    inv_hand_invoke_mid = env->GetMethodID(inv_hand_class.get(), "invoke",
-        "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
+  // If we are the <clinit> of this class, just return our storage.
+  //
+  // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
+  // running.
+  if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
+    return klass;
   }
-  DCHECK(env->IsInstanceOf(rcvr_jobj, env->FindClass("java/lang/reflect/Proxy")));
-  jobject inv_hand = env->GetObjectField(rcvr_jobj, proxy_inv_hand_fid);
-  // Call InvocationHandler.invoke
-  jobject result = env->CallObjectMethodA(inv_hand, inv_hand_invoke_mid, args_jobj);
-  // Place result in stack args
-  if (!self->IsExceptionPending()) {
-    Object* result_ref = self->DecodeJObject(result);
-    if (result_ref != NULL) {
-      JValue result_unboxed;
-      bool unboxed_okay = UnboxPrimitive(result_ref, proxy_mh.GetReturnType(), result_unboxed, "result");
-      if (!unboxed_okay) {
-        self->ClearException();
-        self->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
-                                 "Couldn't convert result of type %s to %s",
-                                 PrettyTypeOf(result_ref).c_str(),
-                                 PrettyDescriptor(proxy_mh.GetReturnType()).c_str());
-        return;
-      }
-      *reinterpret_cast<JValue*>(stack_args) = result_unboxed;
-    } else {
-      *reinterpret_cast<jobject*>(stack_args) = NULL;
-    }
-  } else {
-    // In the case of checked exceptions that aren't declared, the exception must be wrapped by
-    // a UndeclaredThrowableException.
-    Throwable* exception = self->GetException();
-    self->ClearException();
-    if (!exception->IsCheckedException()) {
-      self->SetException(exception);
-    } else {
-      SynthesizedProxyClass* proxy_class =
-          down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass());
-      int throws_index = -1;
-      size_t num_virt_methods = proxy_class->NumVirtualMethods();
-      for (size_t i = 0; i < num_virt_methods; i++) {
-        if (proxy_class->GetVirtualMethod(i) == proxy_method) {
-          throws_index = i;
-          break;
-        }
-      }
-      CHECK_NE(throws_index, -1);
-      ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
-      Class* exception_class = exception->GetClass();
-      bool declares_exception = false;
-      for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
-        Class* declared_exception = declared_exceptions->Get(i);
-        declares_exception = declared_exception->IsAssignableFrom(exception_class);
-      }
-      if (declares_exception) {
-        self->SetException(exception);
-      } else {
-        ThrowNewUndeclaredThrowableException(self, env, exception);
-      }
-    }
+  if (!class_linker->EnsureInitialized(klass, true)) {
+    CHECK(self->IsExceptionPending());
+    return NULL;  // Failure - Indicate to caller to deliver exception
   }
-}
-
-extern "C" const void* artTraceMethodEntryFromCode(Method* method, Thread* self, uintptr_t lr) {
-  Trace* tracer = Runtime::Current()->GetTracer();
-  TraceStackFrame trace_frame = TraceStackFrame(method, lr);
-  self->PushTraceStackFrame(trace_frame);
-
-  tracer->LogMethodTraceEvent(self, method, Trace::kMethodTraceEnter);
-
-  return tracer->GetSavedCodeFromMap(method);
-}
-
-extern "C" uintptr_t artTraceMethodExitFromCode() {
-  Trace* tracer = Runtime::Current()->GetTracer();
-  TraceStackFrame trace_frame = Thread::Current()->PopTraceStackFrame();
-  Method* method = trace_frame.method_;
-  uintptr_t lr = trace_frame.return_pc_;
-
-  tracer->LogMethodTraceEvent(Thread::Current(), method, Trace::kMethodTraceExit);
-
-  return lr;
-}
-
-uint32_t TraceMethodUnwindFromCode(Thread* self) {
-  Trace* tracer = Runtime::Current()->GetTracer();
-  TraceStackFrame trace_frame = self->PopTraceStackFrame();
-  Method* method = trace_frame.method_;
-  uint32_t lr = trace_frame.return_pc_;
-
-  tracer->LogMethodTraceEvent(self, method, Trace::kMethodTraceUnwind);
-
-  return lr;
-}
-
-int CmplFloat(float a, float b) {
-  if (a == b) {
-    return 0;
-  } else if (a < b) {
-    return -1;
-  } else if (a > b) {
-    return 1;
-  }
-  return -1;
-}
-
-int CmpgFloat(float a, float b) {
-  if (a == b) {
-    return 0;
-  } else if (a < b) {
-    return -1;
-  } else if (a > b) {
-    return 1;
-  }
-  return 1;
-}
-
-int CmpgDouble(double a, double b) {
-  if (a == b) {
-    return 0;
-  } else if (a < b) {
-    return -1;
-  } else if (a > b) {
-    return 1;
-  }
-  return 1;
-}
-
-int CmplDouble(double a, double b) {
-  if (a == b) {
-    return 0;
-  } else if (a < b) {
-    return -1;
-  } else if (a > b) {
-    return 1;
-  }
-  return -1;
-}
-
-/*
- * Float/double conversion requires clamping to min and max of integer form.  If
- * target doesn't support this normally, use these.
- */
-int64_t D2L(double d) {
-  static const double kMaxLong = (double) (int64_t) 0x7fffffffffffffffULL;
-  static const double kMinLong = (double) (int64_t) 0x8000000000000000ULL;
-  if (d >= kMaxLong) {
-    return (int64_t) 0x7fffffffffffffffULL;
-  } else if (d <= kMinLong) {
-    return (int64_t) 0x8000000000000000ULL;
-  } else if (d != d)  { // NaN case
-    return 0;
-  } else {
-    return (int64_t) d;
-  }
-}
-
-int64_t F2L(float f) {
-  static const float kMaxLong = (float) (int64_t) 0x7fffffffffffffffULL;
-  static const float kMinLong = (float) (int64_t) 0x8000000000000000ULL;
-  if (f >= kMaxLong) {
-    return (int64_t) 0x7fffffffffffffffULL;
-  } else if (f <= kMinLong) {
-    return (int64_t) 0x8000000000000000ULL;
-  } else if (f != f) { // NaN case
-    return 0;
-  } else {
-    return (int64_t) f;
-  }
+  referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
+  return klass;
 }
 
 }  // namespace art
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 35f88b5..909fb41 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -1,180 +1,195 @@
-/*
- * 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.
- */
+// Copyright 2012 Google Inc. All Rights Reserved.
 
 #ifndef ART_SRC_RUNTIME_SUPPORT_H_
 #define ART_SRC_RUNTIME_SUPPORT_H_
 
 #include "class_linker.h"
+#include "dex_file.h"
+#include "dex_verifier.h"
 #include "object.h"
-#include "thread_list.h"
-#include "utils.h"
+#include "object_utils.h"
+#include "thread.h"
+
+extern "C" void art_proxy_invoke_handler();
+extern "C" void art_work_around_app_jni_bugs();
 
 namespace art {
 
-extern void CheckSuspendFromCode(Thread* thread);
+class Array;
+class Class;
+class Field;
+class Method;
+class Object;
+
+// Helpers to give consistent descriptive exception messages
+void ThrowNewIllegalAccessErrorClass(Thread* self, Class* referrer, Class* accessed);
+void ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self, Class* referrer,
+                                                      Class* accessed,
+                                                      const Method* caller,
+                                                      const Method* called,
+                                                      InvokeType type);
+void ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
+                                                                   const Method* referrer,
+                                                                   const Method* interface_method,
+                                                                   Object* this_object);
+void ThrowNewIllegalAccessErrorField(Thread* self, Class* referrer, Field* accessed);
+void ThrowNewIllegalAccessErrorFinalField(Thread* self, const Method* referrer, Field* accessed);
+
+void ThrowNewIllegalAccessErrorMethod(Thread* self, Class* referrer, Method* accessed);
+void ThrowNullPointerExceptionForFieldAccess(Thread* self, Field* field, bool is_read);
+void ThrowNullPointerExceptionForMethodAccess(Thread* self, Method* caller, uint32_t method_idx,
+                                              InvokeType type);
+
+std::string FieldNameFromIndex(const Method* method, uint32_t ref,
+                               verifier::VerifyErrorRefType ref_type, bool access);
+std::string MethodNameFromIndex(const Method* method, uint32_t ref,
+                                verifier::VerifyErrorRefType ref_type, bool access);
+
+// Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it
+// cannot be resolved, throw an error. If it can, use it to create an instance.
+// When verification/compiler hasn't been able to verify access, optionally perform an access
+// check.
+static inline Object* AllocObjectFromCode(uint32_t type_idx, Method* method, Thread* self,
+                                          bool access_check) {
+  Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+  Runtime* runtime = Runtime::Current();
+  if (UNLIKELY(klass == NULL)) {
+    klass = runtime->GetClassLinker()->ResolveType(type_idx, method);
+    if (klass == NULL) {
+      DCHECK(self->IsExceptionPending());
+      return NULL;  // Failure
+    }
+  }
+  if (access_check) {
+    if (UNLIKELY(!klass->IsInstantiable())) {
+      self->ThrowNewException("Ljava/lang/InstantiationError;",
+                              PrettyDescriptor(klass).c_str());
+      return NULL;  // Failure
+    }
+    Class* referrer = method->GetDeclaringClass();
+    if (UNLIKELY(!referrer->CanAccess(klass))) {
+      ThrowNewIllegalAccessErrorClass(self, referrer, klass);
+      return NULL;  // Failure
+    }
+  }
+  if (!runtime->GetClassLinker()->EnsureInitialized(klass, true)) {
+    DCHECK(self->IsExceptionPending());
+    return NULL;  // Failure
+  }
+  return klass->AllocObject();
+}
+
+// Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If
+// it cannot be resolved, throw an error. If it can, use it to create an array.
+// When verification/compiler hasn't been able to verify access, optionally perform an access
+// check.
+static inline Array* AllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
+                                        Thread* self, bool access_check) {
+  if (UNLIKELY(component_count < 0)) {
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d",
+                                          component_count);
+    return NULL;  // Failure
+  }
+  Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+  if (UNLIKELY(klass == NULL)) {  // Not in dex cache so try to resolve
+    klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
+    if (klass == NULL) {  // Error
+      DCHECK(Thread::Current()->IsExceptionPending());
+      return NULL;  // Failure
+    }
+    CHECK(klass->IsArrayClass()) << PrettyClass(klass);
+  }
+  if (access_check) {
+    Class* referrer = method->GetDeclaringClass();
+    if (UNLIKELY(!referrer->CanAccess(klass))) {
+      ThrowNewIllegalAccessErrorClass(self, referrer, klass);
+      return NULL;  // Failure
+    }
+  }
+  return Array::Alloc(klass, component_count);
+}
+
 extern Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
                                          Thread* self, bool access_check);
-extern void DebugMe(Method* method, uint32_t info);
-extern void UpdateDebuggerFromCode(Method* method, Thread* thread , int32_t dex_pc, Method** sp);
-extern Object* DecodeJObjectInThread(Thread* thread, jobject obj);
+
 extern Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
-                                bool is_static, bool is_primitive, bool is_set, size_t expected_size);
-extern void* FindNativeMethod(Thread* thread);
-extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
-const void* UnresolvedDirectMethodTrampolineFromCode(Method*, Method**, Thread*,
-                                                     Runtime::TrampolineType);
+                                bool is_static, bool is_primitive, bool is_set,
+                                size_t expected_size);
+
+// Fast path field resolution that can't throw exceptions
+static inline Field* FindFieldFast(uint32_t field_idx, const Method* referrer, bool is_primitive,
+                                   size_t expected_size, bool is_set) {
+  Field* resolved_field = referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx);
+  if (UNLIKELY(resolved_field == NULL)) {
+    return NULL;
+  }
+  Class* fields_class = resolved_field->GetDeclaringClass();
+  // Check class is initiliazed or initializing
+  if (UNLIKELY(!fields_class->IsInitializing())) {
+    return NULL;
+  }
+  Class* referring_class = referrer->GetDeclaringClass();
+  if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
+               !referring_class->CanAccessMember(fields_class,
+                                                 resolved_field->GetAccessFlags()) ||
+               (is_set && resolved_field->IsFinal() && (fields_class != referring_class)))) {
+    // illegal access
+    return NULL;
+  }
+  FieldHelper fh(resolved_field);
+  if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
+               fh.FieldSize() != expected_size)) {
+    return NULL;
+  }
+  return resolved_field;
+}
+
+// Fast path method resolution that can't throw exceptions
+static inline Method* FindMethodFast(uint32_t method_idx, Object* this_object, const Method* referrer,
+                              bool access_check, InvokeType type) {
+  bool is_direct = type == kStatic || type == kDirect;
+  if (UNLIKELY(this_object == NULL && !is_direct)) {
+    return NULL;
+  }
+  Method* resolved_method =
+      referrer->GetDeclaringClass()->GetDexCache()->GetResolvedMethod(method_idx);
+  if (UNLIKELY(resolved_method == NULL)) {
+    return NULL;
+  }
+  if (access_check) {
+    Class* methods_class = resolved_method->GetDeclaringClass();
+    Class* referring_class = referrer->GetDeclaringClass();
+    if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
+                 !referring_class->CanAccessMember(methods_class,
+                                                   resolved_method->GetAccessFlags()))) {
+      // potential illegal access
+      return NULL;
+    }
+  }
+  if (type == kInterface) {  // Most common form of slow path dispatch.
+    return this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
+  } else if (is_direct) {
+    return resolved_method;
+  } else if (type == kSuper) {
+    return referrer->GetDeclaringClass()->GetSuperClass()->GetVTable()->
+        Get(resolved_method->GetMethodIndex());
+  } else {
+    DCHECK(type == kVirtual);
+    return this_object->GetClass()->GetVTable()->Get(resolved_method->GetMethodIndex());
+  }
+}
+
+extern Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
+                                  Thread* self, bool access_check, InvokeType type);
+
 extern Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
                                      bool can_run_clinit, bool verify_access);
-extern Class* InitializeTypeFromCode(uint32_t type_idx, Method* method);
-uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class);
-void ObjectInitFromCode(Object* o);
-extern void LockObjectFromCode(Thread* thread, Object* obj);
-uint32_t TraceMethodUnwindFromCode(Thread* self);
-extern int32_t CmpgDouble(double a, double b);
-extern int32_t CmplDouble(double a, double b);
-extern int32_t CmpgFloat(float a, float b);
-extern int32_t CmplFloat(float a, float b);
-extern int64_t D2L(double d);
-extern int64_t F2L(float f);
+
+static inline String* ResolveStringFromCode(const Method* referrer, uint32_t string_idx) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  return class_linker->ResolveString(string_idx, referrer);
+}
 
 }  // namespace art
 
-// Helpers for both compiled code and libart.
-extern "C" void art_deliver_exception_from_code(void*);
-extern "C" void art_proxy_invoke_handler();
-extern "C" void art_update_debugger(void*, void*, int32_t, void*);
-
-#if defined(__arm__)
-  /* Compiler helpers */
-  extern "C" int32_t __memcmp16(void*, void*, int32_t);
-  extern "C" int32_t art_indexof(void*, uint32_t, uint32_t, uint32_t);
-  extern "C" int32_t art_string_compareto(void*, void*);
-  extern "C" int32_t art_get32_static_from_code(uint32_t);
-  extern "C" int64_t art_get64_static_from_code(uint32_t);
-  extern "C" void* art_get_obj_static_from_code(uint32_t);
-  extern "C" int32_t art_get32_instance_from_code(uint32_t, void*);
-  extern "C" int64_t art_get64_instance_from_code(uint32_t, void*);
-  extern "C" void* art_get_obj_instance_from_code(uint32_t, void*);
-  extern "C" int art_set32_static_from_code(uint32_t, int32_t);
-  extern "C" int art_set64_static_from_code(uint32_t, int64_t);
-  extern "C" int art_set_obj_static_from_code(uint32_t, void*);
-  extern "C" int art_set32_instance_from_code(uint32_t, void*, int32_t);
-  extern "C" int art_set64_instance_from_code(uint32_t, void*, int64_t);
-  extern "C" int art_set_obj_instance_from_code(uint32_t, void*, void*);
-  extern "C" void art_can_put_array_element_from_code(void*, void*);
-  extern "C" void art_check_cast_from_code(void*, void*);
-  extern "C" void art_do_long_jump(uint32_t*, uint32_t*);
-  extern "C" void art_handle_fill_data_from_code(void*, void*);
-  extern "C" void art_invoke_direct_trampoline_with_access_check(uint32_t, void*);
-  extern "C" void art_invoke_interface_trampoline(uint32_t, void*);
-  extern "C" void art_invoke_interface_trampoline_with_access_check(uint32_t, void*);
-  extern "C" void art_invoke_static_trampoline_with_access_check(uint32_t, void*);
-  extern "C" void art_invoke_super_trampoline_with_access_check(uint32_t, void*);
-  extern "C" void art_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
-  extern "C" void art_lock_object_from_code(void*);
-  extern "C" void art_test_suspend();
-  extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
-  extern "C" void art_throw_div_zero_from_code();
-  extern "C" void art_throw_neg_array_size_from_code(int32_t size);
-  extern "C" void art_throw_no_such_method_from_code(int32_t method_idx);
-  extern "C" void art_throw_null_pointer_exception_from_code();
-  extern "C" void art_throw_stack_overflow_from_code(void*);
-  extern "C" void art_throw_verification_error_from_code(int32_t src1, int32_t ref);
-  extern "C" void art_unlock_object_from_code(void*);
-  extern "C" void* art_alloc_array_from_code(uint32_t, void*, int32_t);
-  extern "C" void* art_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-  extern "C" void* art_alloc_object_from_code(uint32_t type_idx, void* method);
-  extern "C" void* art_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
-  extern "C" void* art_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
-  extern "C" void* art_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-  extern "C" void* art_initialize_static_storage_from_code(uint32_t, void*);
-  extern "C" void* art_initialize_type_from_code(uint32_t, void*);
-  extern "C" void* art_initialize_type_and_verify_access_from_code(uint32_t, void*);
-  extern "C" void art_trace_entry_from_code(void*);
-  extern "C" void art_trace_exit_from_code();
-  extern "C" void* art_resolve_string_from_code(void*, uint32_t);
-  extern "C" void art_work_around_app_jni_bugs();
-
-  /* Conversions */
-  extern "C" float __aeabi_i2f(int32_t op1);         // INT_TO_FLOAT
-  extern "C" int32_t __aeabi_f2iz(float op1);        // FLOAT_TO_INT
-  extern "C" float __aeabi_d2f(double op1);          // DOUBLE_TO_FLOAT
-  extern "C" double __aeabi_f2d(float op1);          // FLOAT_TO_DOUBLE
-  extern "C" double __aeabi_i2d(int32_t op1);        // INT_TO_DOUBLE
-  extern "C" int32_t __aeabi_d2iz(double op1);       // DOUBLE_TO_INT
-  extern "C" float __aeabi_l2f(int64_t op1);         // LONG_TO_FLOAT
-  extern "C" double __aeabi_l2d(int64_t op1);        // LONG_TO_DOUBLE
-
-  /* Single-precision FP arithmetics */
-  extern "C" float __aeabi_fadd(float a, float b);   // ADD_FLOAT[_2ADDR]
-  extern "C" float __aeabi_fsub(float a, float b);   // SUB_FLOAT[_2ADDR]
-  extern "C" float __aeabi_fdiv(float a, float b);   // DIV_FLOAT[_2ADDR]
-  extern "C" float __aeabi_fmul(float a, float b);   // MUL_FLOAT[_2ADDR]
-  extern "C" float fmodf(float a, float b);          // REM_FLOAT[_2ADDR]
-
-  /* Double-precision FP arithmetics */
-  extern "C" double __aeabi_dadd(double a, double b); // ADD_DOUBLE[_2ADDR]
-  extern "C" double __aeabi_dsub(double a, double b); // SUB_DOUBLE[_2ADDR]
-  extern "C" double __aeabi_ddiv(double a, double b); // DIV_DOUBLE[_2ADDR]
-  extern "C" double __aeabi_dmul(double a, double b); // MUL_DOUBLE[_2ADDR]
-  extern "C" double fmod(double a, double b);         // REM_DOUBLE[_2ADDR]
-
-  /* Integer arithmetics */
-  extern "C" int __aeabi_idivmod(int32_t op1, int32_t op2);  // REM_INT[_2ADDR|_LIT8|_LIT16]
-  extern "C" int __aeabi_idiv(int32_t op1, int32_t op2);     // DIV_INT[_2ADDR|_LIT8|_LIT16]
-
-  /* Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR] */
-  extern "C" long long __aeabi_ldivmod(long long op1, long long op2);
-  extern "C" long long __aeabi_lmul(long long op1, long long op2);
-  extern "C" uint64_t art_shl_long(uint64_t, uint32_t);
-  extern "C" uint64_t art_shr_long(uint64_t, uint32_t);
-  extern "C" uint64_t art_ushr_long(uint64_t, uint32_t);
-
-#endif
-
-#if defined(__mips__)
-  /* Conversions */
-  extern "C" float __floatsisf(int op1);        // INT_TO_FLOAT
-  extern "C" int32_t __fixsfsi(float op1);      // FLOAT_TO_INT
-  extern "C" float __truncdfsf2(double op1);    // DOUBLE_TO_FLOAT
-  extern "C" double __extendsfdf2(float op1);   // FLOAT_TO_DOUBLE
-  extern "C" double __floatsidf(int op1);       // INT_TO_DOUBLE
-  extern "C" int32_t __fixdfsi(double op1);     // DOUBLE_TO_INT
-  extern "C" float __floatdisf(int64_t op1);    // LONG_TO_FLOAT
-  extern "C" double __floatdidf(int64_t op1);   // LONG_TO_DOUBLE
-  extern "C" int64_t __fixsfdi(float op1);      // FLOAT_TO_LONG
-  extern "C" int64_t __fixdfdi(double op1);     // DOUBLE_TO_LONG
-
-  /* Single-precision FP arithmetics */
-  extern "C" float __addsf3(float a, float b);   // ADD_FLOAT[_2ADDR]
-  extern "C" float __subsf3(float a, float b);   // SUB_FLOAT[_2ADDR]
-  extern "C" float __divsf3(float a, float b);   // DIV_FLOAT[_2ADDR]
-  extern "C" float __mulsf3(float a, float b);   // MUL_FLOAT[_2ADDR]
-  extern "C" float fmodf(float a, float b);      // REM_FLOAT[_2ADDR]
-
-  /* Double-precision FP arithmetics */
-  extern "C" double __adddf3(double a, double b); // ADD_DOUBLE[_2ADDR]
-  extern "C" double __subdf3(double a, double b); // SUB_DOUBLE[_2ADDR]
-  extern "C" double __divdf3(double a, double b); // DIV_DOUBLE[_2ADDR]
-  extern "C" double __muldf3(double a, double b); // MUL_DOUBLE[_2ADDR]
-  extern "C" double fmod(double a, double b);     // REM_DOUBLE[_2ADDR]
-
-  /* Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR] */
-  extern "C" long long __divdi3(int64_t op1, int64_t op2);
-  extern "C" long long __moddi3(int64_t op1, int64_t op2);
-#endif
-
 #endif  // ART_SRC_RUNTIME_SUPPORT_H_
diff --git a/src/runtime_support_common.cc b/src/runtime_support_common.cc
deleted file mode 100644
index 71567a3..0000000
--- a/src/runtime_support_common.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-
-#include "runtime_support_common.h"
-
-
-namespace art {
-
-// Helper function to allocate array for FILLED_NEW_ARRAY.
-Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
-                                  Thread* self, bool access_check) {
-  if (UNLIKELY(component_count < 0)) {
-    self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
-    return NULL;  // Failure
-  }
-  Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
-  if (UNLIKELY(klass == NULL)) {  // Not in dex cache so try to resolve
-    klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
-    if (klass == NULL) {  // Error
-      DCHECK(Thread::Current()->IsExceptionPending());
-      return NULL;  // Failure
-    }
-  }
-  if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
-    if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
-      Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
-                                            "Bad filled array request for type %s",
-                                            PrettyDescriptor(klass).c_str());
-    } else {
-      Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;",
-                                            "Found type %s; filled-new-array not implemented for anything but \'int\'",
-                                            PrettyDescriptor(klass).c_str());
-    }
-    return NULL;  // Failure
-  } else {
-    if (access_check) {
-      Class* referrer = method->GetDeclaringClass();
-      if (UNLIKELY(!referrer->CanAccess(klass))) {
-        ThrowNewIllegalAccessErrorClass(self, referrer, klass);
-        return NULL;  // Failure
-      }
-    }
-    DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
-    return Array::Alloc(klass, component_count);
-  }
-}
-
-// Slow path field resolution and declaring class initialization
-Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
-                         bool is_static, bool is_primitive, bool is_set, size_t expected_size) {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
-  if (UNLIKELY(resolved_field == NULL)) {
-    DCHECK(self->IsExceptionPending());  // Throw exception and unwind
-    return NULL;  // failure
-  } else {
-    Class* fields_class = resolved_field->GetDeclaringClass();
-    Class* referring_class = referrer->GetDeclaringClass();
-    if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
-      ThrowNewIllegalAccessErrorClass(self, referring_class, fields_class);
-      return NULL;  // failure
-    } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
-                                                          resolved_field->GetAccessFlags()))) {
-      ThrowNewIllegalAccessErrorField(self, referring_class, resolved_field);
-      return NULL;  // failure
-    } else if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
-      ThrowNewIllegalAccessErrorFinalField(self, referrer, resolved_field);
-      return NULL;  // failure
-    } else {
-      FieldHelper fh(resolved_field);
-      if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
-                   fh.FieldSize() != expected_size)) {
-        self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
-                                 "Attempted read of %zd-bit %s on field '%s'",
-                                 expected_size * (32 / sizeof(int32_t)),
-                                 is_primitive ? "primitive" : "non-primitive",
-                                 PrettyField(resolved_field, true).c_str());
-        return NULL;  // failure
-      } else if (!is_static) {
-        // instance fields must be being accessed on an initialized class
-        return resolved_field;
-      } else {
-        // If the class is already initializing, we must be inside <clinit>, or
-        // we'd still be waiting for the lock.
-        if (fields_class->IsInitializing()) {
-          return resolved_field;
-        } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true)) {
-          return resolved_field;
-        } else {
-          DCHECK(self->IsExceptionPending());  // Throw exception and unwind
-          return NULL;  // failure
-        }
-      }
-    }
-  }
-}
-
-// Slow path method resolution
-Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
-                           Thread* self, bool access_check, InvokeType type) {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  bool is_direct = type == kStatic || type == kDirect;
-  Method* resolved_method = class_linker->ResolveMethod(method_idx, referrer, is_direct);
-  if (UNLIKELY(resolved_method == NULL)) {
-    DCHECK(self->IsExceptionPending());  // Throw exception and unwind
-    return NULL;  // failure
-  } else {
-    if (!access_check) {
-      if (is_direct) {
-        return resolved_method;
-      } else if (type == kInterface) {
-        Method* interface_method =
-            this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
-        if (UNLIKELY(interface_method == NULL)) {
-          ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
-                                                                        resolved_method,
-                                                                        this_object);
-          return NULL;  // failure
-        } else {
-          return interface_method;
-        }
-      } else {
-        ObjectArray<Method>* vtable;
-        uint16_t vtable_index = resolved_method->GetMethodIndex();
-        if (type == kSuper) {
-          vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
-        } else {
-          vtable = this_object->GetClass()->GetVTable();
-        }
-        // TODO: eliminate bounds check?
-        return vtable->Get(vtable_index);
-      }
-    } else {
-      Class* methods_class = resolved_method->GetDeclaringClass();
-      Class* referring_class = referrer->GetDeclaringClass();
-      if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
-                   !referring_class->CanAccessMember(methods_class,
-                                                     resolved_method->GetAccessFlags()))) {
-        // The referring class can't access the resolved method, this may occur as a result of a
-        // protected method being made public by implementing an interface that re-declares the
-        // method public. Resort to the dex file to determine the correct class for the access check
-        const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
-        methods_class = class_linker->ResolveType(dex_file,
-                                                  dex_file.GetMethodId(method_idx).class_idx_,
-                                                  referring_class);
-        if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
-          ThrowNewIllegalAccessErrorClassForMethodDispatch(self, referring_class, methods_class,
-                                                           referrer, resolved_method, type);
-          return NULL;  // failure
-        } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
-                                                              resolved_method->GetAccessFlags()))) {
-          ThrowNewIllegalAccessErrorMethod(self, referring_class, resolved_method);
-          return NULL;  // failure
-        }
-      }
-      if (is_direct) {
-        return resolved_method;
-      } else if (type == kInterface) {
-        Method* interface_method =
-            this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
-        if (UNLIKELY(interface_method == NULL)) {
-          ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
-                                                                        resolved_method,
-                                                                        this_object);
-          return NULL;  // failure
-        } else {
-          return interface_method;
-        }
-      } else {
-        ObjectArray<Method>* vtable;
-        uint16_t vtable_index = resolved_method->GetMethodIndex();
-        if (type == kSuper) {
-          Class* super_class = referring_class->GetSuperClass();
-          if (LIKELY(super_class != NULL)) {
-            vtable = referring_class->GetSuperClass()->GetVTable();
-          } else {
-            vtable = NULL;
-          }
-        } else {
-          vtable = this_object->GetClass()->GetVTable();
-        }
-        if (LIKELY(vtable != NULL &&
-                   vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
-          return vtable->GetWithoutChecks(vtable_index);
-        } else {
-          // Behavior to agree with that of the verifier
-          self->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
-                                   "attempt to invoke %s method '%s' from '%s'"
-                                   " using incorrect form of method dispatch",
-                                   (type == kSuper ? "super class" : "virtual"),
-                                   PrettyMethod(resolved_method).c_str(),
-                                   PrettyMethod(referrer).c_str());
-          return NULL;  // failure
-        }
-      }
-    }
-  }
-}
-
-Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
-                               bool can_run_clinit, bool verify_access) {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Class* klass = class_linker->ResolveType(type_idx, referrer);
-  if (UNLIKELY(klass == NULL)) {
-    CHECK(self->IsExceptionPending());
-    return NULL;  // Failure - Indicate to caller to deliver exception
-  }
-  // Perform access check if necessary.
-  Class* referring_class = referrer->GetDeclaringClass();
-  if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
-    ThrowNewIllegalAccessErrorClass(self, referring_class, klass);
-    return NULL;  // Failure - Indicate to caller to deliver exception
-  }
-  // If we're just implementing const-class, we shouldn't call <clinit>.
-  if (!can_run_clinit) {
-    return klass;
-  }
-  // If we are the <clinit> of this class, just return our storage.
-  //
-  // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
-  // running.
-  if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
-    return klass;
-  }
-  if (!class_linker->EnsureInitialized(klass, true)) {
-    CHECK(self->IsExceptionPending());
-    return NULL;  // Failure - Indicate to caller to deliver exception
-  }
-  referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
-  return klass;
-}
-
-}  // namespace art
diff --git a/src/runtime_support_common.h b/src/runtime_support_common.h
deleted file mode 100644
index c5121a9..0000000
--- a/src/runtime_support_common.h
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
-
-#ifndef ART_SRC_RUNTIME_SUPPORT_COMMON_H_
-#define ART_SRC_RUNTIME_SUPPORT_COMMON_H_
-
-#include "class_linker.h"
-#include "constants.h"
-#include "object.h"
-#include "object_utils.h"
-#include "thread.h"
-
-#include <stdint.h>
-
-namespace art {
-
-class Array;
-class Class;
-class Field;
-class Method;
-class Object;
-
-static inline void ThrowNewIllegalAccessErrorClass(Thread* self,
-                                                   Class* referrer,
-                                                   Class* accessed) {
-  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-                           "illegal class access: '%s' -> '%s'",
-                           PrettyDescriptor(referrer).c_str(),
-                           PrettyDescriptor(accessed).c_str());
-}
-
-static inline void
-ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self,
-                                                 Class* referrer,
-                                                 Class* accessed,
-                                                 const Method* caller,
-                                                 const Method* called,
-                                                 InvokeType type) {
-  std::ostringstream type_stream;
-  type_stream << type;
-  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-                           "illegal class access ('%s' -> '%s')"
-                           "in attempt to invoke %s method '%s' from '%s'",
-                           PrettyDescriptor(referrer).c_str(),
-                           PrettyDescriptor(accessed).c_str(),
-                           type_stream.str().c_str(),
-                           PrettyMethod(called).c_str(),
-                           PrettyMethod(caller).c_str());
-}
-
-static inline void
-ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
-                                                              const Method* referrer,
-                                                              const Method* interface_method,
-                                                              Object* this_object) {
-  self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
-                           "class '%s' does not implement interface '%s' in call to '%s' from '%s'",
-                           PrettyDescriptor(this_object->GetClass()).c_str(),
-                           PrettyDescriptor(interface_method->GetDeclaringClass()).c_str(),
-                           PrettyMethod(interface_method).c_str(), PrettyMethod(referrer).c_str());
-}
-
-static inline void ThrowNewIllegalAccessErrorField(Thread* self,
-                                                   Class* referrer,
-                                                   Field* accessed) {
-  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-                           "Field '%s' is inaccessible to class '%s'",
-                           PrettyField(accessed, false).c_str(),
-                           PrettyDescriptor(referrer).c_str());
-}
-
-static inline void ThrowNewIllegalAccessErrorFinalField(Thread* self,
-                                                        const Method* referrer,
-                                                        Field* accessed) {
-  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-                           "Final field '%s' cannot be written to by method '%s'",
-                           PrettyField(accessed, false).c_str(),
-                           PrettyMethod(referrer).c_str());
-}
-
-static inline void ThrowNewIllegalAccessErrorMethod(Thread* self,
-                                                    Class* referrer,
-                                                    Method* accessed) {
-  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-                           "Method '%s' is inaccessible to class '%s'",
-                           PrettyMethod(accessed).c_str(),
-                           PrettyDescriptor(referrer).c_str());
-}
-
-static inline void ThrowNullPointerExceptionForFieldAccess(Thread* self,
-                                                           Field* field,
-                                                           bool is_read) {
-  self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
-                           "Attempt to %s field '%s' on a null object reference",
-                           is_read ? "read from" : "write to",
-                           PrettyField(field, true).c_str());
-}
-
-static inline void ThrowNullPointerExceptionForMethodAccess(Thread* self,
-                                                            Method* caller,
-                                                            uint32_t method_idx,
-                                                            InvokeType type) {
-  const DexFile& dex_file =
-      Runtime::Current()->GetClassLinker()->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
-  std::ostringstream type_stream;
-  type_stream << type;
-  self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
-                           "Attempt to invoke %s method '%s' on a null object reference",
-                           type_stream.str().c_str(),
-                           PrettyMethod(method_idx, dex_file, true).c_str());
-}
-
-// Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it
-// cannot be resolved, throw an error. If it can, use it to create an instance.
-// When verification/compiler hasn't been able to verify access, optionally perform an access
-// check.
-static inline Object* AllocObjectFromCode(uint32_t type_idx, Method* method, Thread* self,
-                                          bool access_check) {
-  Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
-  Runtime* runtime = Runtime::Current();
-  if (UNLIKELY(klass == NULL)) {
-    klass = runtime->GetClassLinker()->ResolveType(type_idx, method);
-    if (klass == NULL) {
-      DCHECK(self->IsExceptionPending());
-      return NULL;  // Failure
-    }
-  }
-  if (access_check) {
-    if (UNLIKELY(!klass->IsInstantiable())) {
-      self->ThrowNewException("Ljava/lang/InstantiationError;",
-                              PrettyDescriptor(klass).c_str());
-      return NULL;  // Failure
-    }
-    Class* referrer = method->GetDeclaringClass();
-    if (UNLIKELY(!referrer->CanAccess(klass))) {
-      ThrowNewIllegalAccessErrorClass(self, referrer, klass);
-      return NULL;  // Failure
-    }
-  }
-  if (!runtime->GetClassLinker()->EnsureInitialized(klass, true)) {
-    DCHECK(self->IsExceptionPending());
-    return NULL;  // Failure
-  }
-  return klass->AllocObject();
-}
-
-// Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If
-// it cannot be resolved, throw an error. If it can, use it to create an array.
-// When verification/compiler hasn't been able to verify access, optionally perform an access
-// check.
-static inline Array* AllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
-                                        Thread* self, bool access_check) {
-  if (UNLIKELY(component_count < 0)) {
-    Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d",
-                                          component_count);
-    return NULL;  // Failure
-  }
-  Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
-  if (UNLIKELY(klass == NULL)) {  // Not in dex cache so try to resolve
-    klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
-    if (klass == NULL) {  // Error
-      DCHECK(Thread::Current()->IsExceptionPending());
-      return NULL;  // Failure
-    }
-    CHECK(klass->IsArrayClass()) << PrettyClass(klass);
-  }
-  if (access_check) {
-    Class* referrer = method->GetDeclaringClass();
-    if (UNLIKELY(!referrer->CanAccess(klass))) {
-      ThrowNewIllegalAccessErrorClass(self, referrer, klass);
-      return NULL;  // Failure
-    }
-  }
-  return Array::Alloc(klass, component_count);
-}
-
-extern Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
-                                         Thread* self, bool access_check);
-
-extern Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
-                                bool is_static, bool is_primitive, bool is_set,
-                                size_t expected_size);
-
-// Fast path field resolution that can't throw exceptions
-static inline Field* FindFieldFast(uint32_t field_idx, const Method* referrer, bool is_primitive,
-                                   size_t expected_size, bool is_set) {
-  Field* resolved_field = referrer->GetDeclaringClass()->GetDexCache()->GetResolvedField(field_idx);
-  if (UNLIKELY(resolved_field == NULL)) {
-    return NULL;
-  }
-  Class* fields_class = resolved_field->GetDeclaringClass();
-  // Check class is initiliazed or initializing
-  if (UNLIKELY(!fields_class->IsInitializing())) {
-    return NULL;
-  }
-  Class* referring_class = referrer->GetDeclaringClass();
-  if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
-               !referring_class->CanAccessMember(fields_class,
-                                                 resolved_field->GetAccessFlags()) ||
-               (is_set && resolved_field->IsFinal() && (fields_class != referring_class)))) {
-    // illegal access
-    return NULL;
-  }
-  FieldHelper fh(resolved_field);
-  if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
-               fh.FieldSize() != expected_size)) {
-    return NULL;
-  }
-  return resolved_field;
-}
-
-// Fast path method resolution that can't throw exceptions
-static inline Method* FindMethodFast(uint32_t method_idx, Object* this_object, const Method* referrer,
-                              bool access_check, InvokeType type) {
-  bool is_direct = type == kStatic || type == kDirect;
-  if (UNLIKELY(this_object == NULL && !is_direct)) {
-    return NULL;
-  }
-  Method* resolved_method =
-      referrer->GetDeclaringClass()->GetDexCache()->GetResolvedMethod(method_idx);
-  if (UNLIKELY(resolved_method == NULL)) {
-    return NULL;
-  }
-  if (access_check) {
-    Class* methods_class = resolved_method->GetDeclaringClass();
-    Class* referring_class = referrer->GetDeclaringClass();
-    if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
-                 !referring_class->CanAccessMember(methods_class,
-                                                   resolved_method->GetAccessFlags()))) {
-      // potential illegal access
-      return NULL;
-    }
-  }
-  if (type == kInterface) {  // Most common form of slow path dispatch.
-    return this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
-  } else if (is_direct) {
-    return resolved_method;
-  } else if (type == kSuper) {
-    return referrer->GetDeclaringClass()->GetSuperClass()->GetVTable()->
-        Get(resolved_method->GetMethodIndex());
-  } else {
-    DCHECK(type == kVirtual);
-    return this_object->GetClass()->GetVTable()->Get(resolved_method->GetMethodIndex());
-  }
-}
-
-extern Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
-                                  Thread* self, bool access_check, InvokeType type);
-
-extern Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
-                                     bool can_run_clinit, bool verify_access);
-
-static inline String* ResolveStringFromCode(const Method* referrer, uint32_t string_idx) {
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  return class_linker->ResolveString(string_idx, referrer);
-}
-
-}  // namespace art
-
-#endif  // ART_SRC_RUNTIME_SUPPORT_COMMON_H_
diff --git a/src/thread.cc b/src/thread.cc
index aee684b..fa78365 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -31,11 +31,11 @@
 #include "debugger.h"
 #include "class_linker.h"
 #include "class_loader.h"
-#include "context.h"
 #include "dex_verifier.h"
 #include "heap.h"
 #include "jni_internal.h"
 #include "monitor.h"
+#include "oat/runtime/context.h"
 #include "object.h"
 #include "object_utils.h"
 #include "reflection.h"
@@ -76,194 +76,12 @@
 }
 
 void Thread::InitFunctionPointers() {
-#if defined(__mips)
-  pShlLong = art_shl_long;
-  pShrLong = art_shr_long;
-  pUshrLong = art_ushr_long;
-  pI2f = __floatsisf;
-  pF2iz = __fixsfi;
-  pD2f = __truncdfsf2;
-  pF2d = __extendsfdfs;
-  pD2iz = __fixdfsi;
-  pL2f = __floatdisf;
-  pL2d = __floatdidf;
-  pFadd = __addsf3;
-  pFsub = __subsf3;
-  pFdiv = divsf3;
-  pFmul = __mulsf3;
-  pFmodf = fmodf;
-  pDadd = __adddf3;
-  pDsub = __subdf3;
-  pDdiv = __divdf3;
-  pDmul = muldf3;
-  pFmod = fmod;
-  pCmpgFloat = CmpgFloat;
-  pCmplFloat = CmplFloat;
-  pCmpgDouble = CmpgDouble;
-  pCmplDouble = CmplDouble;
-#elif defined(__arm__)
-  pMemcmp16 = __memcmp16;
-  pIndexOf = art_indexof;
-  pStringCompareTo = art_string_compareto;
-  pShlLong = art_shl_long;
-  pShrLong = art_shr_long;
-  pUshrLong = art_ushr_long;
-  pIdiv = __aeabi_idiv;
-  pIdivmod = __aeabi_idivmod;
-  pI2f = __aeabi_i2f;
-  pF2iz = __aeabi_f2iz;
-  pD2f = __aeabi_d2f;
-  pF2d = __aeabi_f2d;
-  pD2iz = __aeabi_d2iz;
-  pL2f = __aeabi_l2f;
-  pL2d = __aeabi_l2d;
-  pFadd = __aeabi_fadd;
-  pFsub = __aeabi_fsub;
-  pFdiv = __aeabi_fdiv;
-  pFmul = __aeabi_fmul;
-  pFmodf = fmodf;
-  pDadd = __aeabi_dadd;
-  pDsub = __aeabi_dsub;
-  pDdiv = __aeabi_ddiv;
-  pDmul = __aeabi_dmul;
-  pFmod = fmod;
-  pLadd = NULL;
-  pLsub = NULL;
-  pLand = NULL;
-  pLor = NULL;
-  pLxor = NULL;
-  pLdivmod = __aeabi_ldivmod;
-  pLmul = __aeabi_lmul;
-  pAllocArrayFromCode = art_alloc_array_from_code;
-  pAllocArrayFromCodeWithAccessCheck = art_alloc_array_from_code_with_access_check;
-  pAllocObjectFromCode = art_alloc_object_from_code;
-  pAllocObjectFromCodeWithAccessCheck = art_alloc_object_from_code_with_access_check;
-  pCanPutArrayElementFromCode = art_can_put_array_element_from_code;
-  pCheckAndAllocArrayFromCode = art_check_and_alloc_array_from_code;
-  pCheckAndAllocArrayFromCodeWithAccessCheck = art_check_and_alloc_array_from_code_with_access_check;
-  pCheckCastFromCode = art_check_cast_from_code;
-  pGet32Instance = art_get32_instance_from_code;
-  pGet64Instance = art_get64_instance_from_code;
-  pGetObjInstance = art_get_obj_instance_from_code;
-  pGet32Static = art_get32_static_from_code;
-  pGet64Static = art_get64_static_from_code;
-  pGetObjStatic = art_get_obj_static_from_code;
-  pHandleFillArrayDataFromCode = art_handle_fill_data_from_code;
-  pInitializeStaticStorage = art_initialize_static_storage_from_code;
-  pInitializeTypeFromCode = art_initialize_type_from_code;
-  pInitializeTypeAndVerifyAccessFromCode = art_initialize_type_and_verify_access_from_code;
-  pInvokeDirectTrampolineWithAccessCheck = art_invoke_direct_trampoline_with_access_check;
-  pInvokeInterfaceTrampoline = art_invoke_interface_trampoline;
-  pInvokeInterfaceTrampolineWithAccessCheck = art_invoke_interface_trampoline_with_access_check;
-  pInvokeStaticTrampolineWithAccessCheck = art_invoke_static_trampoline_with_access_check;
-  pInvokeSuperTrampolineWithAccessCheck = art_invoke_super_trampoline_with_access_check;
-  pInvokeVirtualTrampolineWithAccessCheck = art_invoke_virtual_trampoline_with_access_check;
-  pLockObjectFromCode = art_lock_object_from_code;
-  pResolveStringFromCode = art_resolve_string_from_code;
-  pSet32Instance = art_set32_instance_from_code;
-  pSet64Instance = art_set64_instance_from_code;
-  pSetObjInstance = art_set_obj_instance_from_code;
-  pSet32Static = art_set32_static_from_code;
-  pSet64Static = art_set64_static_from_code;
-  pSetObjStatic = art_set_obj_static_from_code;
-  pTestSuspendFromCode = art_test_suspend;
-  pThrowArrayBoundsFromCode = art_throw_array_bounds_from_code;
-  pThrowDivZeroFromCode = art_throw_div_zero_from_code;
-  pThrowNegArraySizeFromCode = art_throw_neg_array_size_from_code;
-  pThrowNoSuchMethodFromCode = art_throw_no_such_method_from_code;
-  pThrowNullPointerFromCode = art_throw_null_pointer_exception_from_code;
-  pThrowStackOverflowFromCode = art_throw_stack_overflow_from_code;
-  pThrowVerificationErrorFromCode = art_throw_verification_error_from_code;
-  pUnlockObjectFromCode = art_unlock_object_from_code;
-#elif defined(__i386__)
-  pShlLong = NULL;
-  pShrLong = NULL;
-  pUshrLong = NULL;
-  pIdiv = NULL;
-  pIdivmod = NULL;
-  pI2f = NULL;
-  pF2iz = NULL;
-  pD2f = NULL;
-  pF2d = NULL;
-  pD2iz = NULL;
-  pL2f = NULL;
-  pL2d = NULL;
-  pFadd = NULL;
-  pFsub = NULL;
-  pFdiv = NULL;
-  pFmul = NULL;
-  pFmodf = NULL;
-  pDadd = NULL;
-  pDsub = NULL;
-  pDdiv = NULL;
-  pDmul = NULL;
-  pFmod = NULL;
-  pLadd = NULL;
-  pLsub = NULL;
-  pLand = NULL;
-  pLor = NULL;
-  pLxor = NULL;
-  pLdivmod = NULL;
-  pLmul = NULL;
-  pAllocArrayFromCode = NULL;
-  pAllocArrayFromCodeWithAccessCheck = NULL;
-  pAllocObjectFromCode = NULL;
-  pAllocObjectFromCodeWithAccessCheck = NULL;
-  pCanPutArrayElementFromCode = NULL;
-  pCheckAndAllocArrayFromCode = NULL;
-  pCheckAndAllocArrayFromCodeWithAccessCheck = NULL;
-  pCheckCastFromCode = NULL;
-  pGet32Instance = NULL;
-  pGet64Instance = NULL;
-  pGetObjInstance = NULL;
-  pGet32Static = NULL;
-  pGet64Static = NULL;
-  pGetObjStatic = NULL;
-  pHandleFillArrayDataFromCode = NULL;
-  pInitializeStaticStorage = NULL;
-  pInitializeTypeFromCode = NULL;
-  pInitializeTypeAndVerifyAccessFromCode = NULL;
-  pInvokeDirectTrampolineWithAccessCheck = NULL;
-  pInvokeInterfaceTrampoline = NULL;
-  pInvokeInterfaceTrampolineWithAccessCheck = NULL;
-  pInvokeStaticTrampolineWithAccessCheck = NULL;
-  pInvokeSuperTrampolineWithAccessCheck = NULL;
-  pInvokeVirtualTrampolineWithAccessCheck = NULL;
-  pLockObjectFromCode = NULL;
-  pResolveStringFromCode = NULL;
-  pSet32Instance = NULL;
-  pSet64Instance = NULL;
-  pSetObjInstance = NULL;
-  pSet32Static = NULL;
-  pSet64Static = NULL;
-  pSetObjStatic = NULL;
-  pTestSuspendFromCode = NULL;
-  pThrowArrayBoundsFromCode = NULL;
-  pThrowDivZeroFromCode = NULL;
-  pThrowNegArraySizeFromCode = NULL;
-  pThrowNoSuchMethodFromCode = NULL;
-  pThrowNullPointerFromCode = NULL;
-  pThrowStackOverflowFromCode = NULL;
-  pThrowVerificationErrorFromCode = NULL;
-  pUnlockObjectFromCode = NULL;
-#endif
-  pF2l = F2L;
-  pD2l = D2L;
-  pMemcpy = memcpy;
-  pCheckSuspendFromCode = CheckSuspendFromCode;
-  pDebugMe = DebugMe;
-  pDecodeJObjectInThread = DecodeJObjectInThread;
-  pDeliverException = art_deliver_exception_from_code;
-  pFindNativeMethod = FindNativeMethod;
-  pInstanceofNonTrivialFromCode = IsAssignableFromCode;
-  pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode;
-  pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
-  pUpdateDebuggerFromCode = NULL; // Controlled by SetDebuggerUpdatesEnabled.
+  InitEntryPoints(&entrypoints_);
 }
 
 void Thread::SetDebuggerUpdatesEnabled(bool enabled) {
   LOG(INFO) << "Turning debugger updates " << (enabled ? "on" : "off") << " for " << *this;
-  pUpdateDebuggerFromCode = (enabled ? art_update_debugger : NULL);
+  ChangeDebuggerEntryPoint(&entrypoints_, enabled);
 }
 
 void Thread::InitTid() {
@@ -1338,30 +1156,29 @@
 void Thread::WalkStack(StackVisitor* visitor, bool include_upcalls) const {
   Frame frame = GetTopOfStack();
   uintptr_t pc = ManglePc(top_of_managed_stack_pc_);
-#if defined(__arm__)
   uint32_t trace_stack_depth = 0;
-#endif
   // TODO: enable this CHECK after native_to_managed_record_ is initialized during startup.
   // CHECK(native_to_managed_record_ != NULL);
   NativeToManagedRecord* record = native_to_managed_record_;
-
+  bool method_tracing_active = Runtime::Current()->IsMethodTracingActive();
   while (frame.GetSP() != NULL) {
     for ( ; frame.GetMethod() != NULL; frame.Next()) {
       frame.GetMethod()->AssertPcIsWithinCode(pc);
       bool should_continue = visitor->VisitFrame(frame, pc);
-      if (!should_continue) {
+      if (UNLIKELY(!should_continue)) {
         return;
       }
-      pc = ManglePc(frame.GetReturnPC());
-      if (Runtime::Current()->IsMethodTracingActive()) {
-#if defined(__arm__)
-        uintptr_t trace_exit = reinterpret_cast<uintptr_t>(art_trace_exit_from_code);
-        if (ManglePc(trace_exit) == pc) {
+      uintptr_t return_pc = frame.GetReturnPC();
+      if (LIKELY(!method_tracing_active)) {
+        pc = ManglePc(return_pc);
+      } else {
+        if (IsTraceExitPc(return_pc)) {
           TraceStackFrame trace_frame = GetTraceStackFrame(trace_stack_depth++);
           CHECK(trace_frame.method_ == frame.GetMethod());
           pc = ManglePc(trace_frame.return_pc_);
+        } else {
+          pc = ManglePc(return_pc);
         }
-#endif
       }
     }
     if (include_upcalls) {
@@ -1626,7 +1443,8 @@
 class CatchBlockStackVisitor : public Thread::StackVisitor {
  public:
   CatchBlockStackVisitor(Class* to_find, Context* ljc)
-      : to_find_(to_find), long_jump_context_(ljc), native_method_count_(0) {
+      : to_find_(to_find), long_jump_context_(ljc), native_method_count_(0),
+        method_tracing_active_(Runtime::Current()->IsMethodTracingActive()) {
 #ifndef NDEBUG
     handler_pc_ = 0xEBADC0DE;
     handler_frame_.SetSP(reinterpret_cast<Method**>(0xEBADF00D));
@@ -1640,24 +1458,20 @@
       // long jump to them
       handler_pc_ = DemanglePc(pc);
       handler_frame_ = fr;
-      return false;
+      return false;  // End stack walk.
     }
     uint32_t dex_pc = DexFile::kDexNoIndex;
-    if (method->IsCalleeSaveMethod()) {
+    if (method->IsRuntimeMethod()) {
       // ignore callee save method
+      DCHECK(method->IsCalleeSaveMethod());
     } else if (method->IsNative()) {
       native_method_count_++;
     } else {
       // Unwind stack during method tracing
-      if (Runtime::Current()->IsMethodTracingActive()) {
-#if defined(__arm__)
-        uintptr_t trace_exit = reinterpret_cast<uintptr_t>(art_trace_exit_from_code);
-        if (ManglePc(trace_exit) == pc) {
+      if (UNLIKELY(method_tracing_active_)) {
+        if (IsTraceExitPc(DemanglePc(pc))) {
           pc = ManglePc(TraceMethodUnwindFromCode(Thread::Current()));
         }
-#else
-        UNIMPLEMENTED(WARNING);
-#endif
       }
       dex_pc = method->ToDexPC(pc);
     }
@@ -1666,12 +1480,12 @@
       if (found_dex_pc != DexFile::kDexNoIndex) {
         handler_pc_ = method->ToNativePC(found_dex_pc);
         handler_frame_ = fr;
-        return false;
+        return false;  // End stack walk.
       }
     }
     // Caller may be handler, fill in callee saves in context
     long_jump_context_->FillCalleeSaves(fr);
-    return true;
+    return true;  // Continue stack walk.
   }
 
   // The type of the exception catch block to find
@@ -1684,6 +1498,8 @@
   Context* long_jump_context_;
   // Number of native methods passed in crawl (equates to number of SIRTs to pop)
   uint32_t native_method_count_;
+  // Is method tracing active?
+  const bool method_tracing_active_;
 };
 
 void Thread::DeliverException() {
diff --git a/src/thread.h b/src/thread.h
index 32e000c..40409b6 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -32,6 +32,7 @@
 #include "macros.h"
 #include "mutex.h"
 #include "mem_map.h"
+#include "oat/runtime/oat_support_entrypoints.h"
 #include "offsets.h"
 #include "runtime_stats.h"
 #include "stack.h"
@@ -615,98 +616,7 @@
 
  public:
   // Runtime support function pointers
-  void (*pDebugMe)(Method*, uint32_t);
-  void* (*pMemcpy)(void*, const void*, size_t);
-  uint64_t (*pShlLong)(uint64_t, uint32_t);
-  uint64_t (*pShrLong)(uint64_t, uint32_t);
-  uint64_t (*pUshrLong)(uint64_t, uint32_t);
-  float (*pI2f)(int);
-  int (*pF2iz)(float);
-  float (*pD2f)(double);
-  double (*pF2d)(float);
-  double (*pI2d)(int);
-  int (*pD2iz)(double);
-  float (*pL2f)(int64_t);
-  double (*pL2d)(int64_t);
-  int64_t (*pF2l)(float);
-  int64_t (*pD2l)(double);
-  float (*pFadd)(float, float);
-  float (*pFsub)(float, float);
-  float (*pFdiv)(float, float);
-  float (*pFmul)(float, float);
-  float (*pFmodf)(float, float);
-  double (*pDadd)(double, double);
-  double (*pDsub)(double, double);
-  double (*pDdiv)(double, double);
-  double (*pDmul)(double, double);
-  double (*pFmod)(double, double);
-  int (*pIdivmod)(int, int);
-  int (*pIdiv)(int, int);
-  int64_t (*pLadd)(int64_t, int64_t);
-  int64_t (*pLsub)(int64_t, int64_t);
-  int64_t (*pLand)(int64_t, int64_t);
-  int64_t (*pLor)(int64_t, int64_t);
-  int64_t (*pLxor)(int64_t, int64_t);
-  int64_t (*pLmul)(int64_t, int64_t);
-  int64_t (*pLdivmod)(int64_t, int64_t);
-  void (*pCheckSuspendFromCode)(Thread*);  // Stub that is called when the suspend count is non-zero
-  void (*pTestSuspendFromCode)();  // Stub that is periodically called to test the suspend count
-  void* (*pAllocObjectFromCode)(uint32_t, void*);
-  void* (*pAllocObjectFromCodeWithAccessCheck)(uint32_t, void*);
-  void* (*pAllocArrayFromCode)(uint32_t, void*, int32_t);
-  void* (*pAllocArrayFromCodeWithAccessCheck)(uint32_t, void*, int32_t);
-  void (*pCanPutArrayElementFromCode)(void*, void*);
-  void* (*pCheckAndAllocArrayFromCode)(uint32_t, void*, int32_t);
-  void* (*pCheckAndAllocArrayFromCodeWithAccessCheck)(uint32_t, void*, int32_t);
-  void (*pCheckCastFromCode)(void*, void*);
-  Object* (*pDecodeJObjectInThread)(Thread* thread, jobject obj);
-  void (*pDeliverException)(void*);
-  Method* (*pFindInterfaceMethodInCache)(Class*, uint32_t, const Method*, struct DvmDex*);
-  void* (*pFindNativeMethod)(Thread* thread);
-  int32_t (*pGet32Instance)(uint32_t, void*);
-  int64_t (*pGet64Instance)(uint32_t, void*);
-  void* (*pGetObjInstance)(uint32_t, void*);
-  int32_t (*pGet32Static)(uint32_t);
-  int64_t (*pGet64Static)(uint32_t);
-  void* (*pGetObjStatic)(uint32_t);
-  void (*pHandleFillArrayDataFromCode)(void*, void*);
-  void* (*pInitializeStaticStorage)(uint32_t, void*);
-  uint32_t (*pInstanceofNonTrivialFromCode)(const Class*, const Class*);
-  void (*pInvokeDirectTrampolineWithAccessCheck)(uint32_t, void*);
-  void (*pInvokeInterfaceTrampoline)(uint32_t, void*);
-  void (*pInvokeInterfaceTrampolineWithAccessCheck)(uint32_t, void*);
-  void (*pInvokeStaticTrampolineWithAccessCheck)(uint32_t, void*);
-  void (*pInvokeSuperTrampolineWithAccessCheck)(uint32_t, void*);
-  void (*pInvokeVirtualTrampolineWithAccessCheck)(uint32_t, void*);
-  void* (*pInitializeTypeFromCode)(uint32_t, void*);
-  void* (*pInitializeTypeAndVerifyAccessFromCode)(uint32_t, void*);
-  void (*pLockObjectFromCode)(void*);
-  void* (*pResolveStringFromCode)(void*, uint32_t);
-  int (*pSet32Instance)(uint32_t, void*, int32_t);  // field_idx, obj, src
-  int (*pSet64Instance)(uint32_t, void*, int64_t);
-  int (*pSetObjInstance)(uint32_t, void*, void*);
-  int (*pSet32Static)(uint32_t, int32_t);
-  int (*pSet64Static)(uint32_t, int64_t);
-  int (*pSetObjStatic)(uint32_t, void*);
-  void (*pThrowStackOverflowFromCode)(void*);
-  void (*pThrowNullPointerFromCode)();
-  void (*pThrowArrayBoundsFromCode)(int32_t, int32_t);
-  void (*pThrowDivZeroFromCode)();
-  void (*pThrowVerificationErrorFromCode)(int32_t, int32_t);
-  void (*pThrowNegArraySizeFromCode)(int32_t);
-  void (*pThrowNoSuchMethodFromCode)(int32_t);
-  void (*pThrowAbstractMethodErrorFromCode)(Method* method, Thread* thread, Method** sp);
-  void (*pUnlockObjectFromCode)(void*);
-  const void* (*pUnresolvedDirectMethodTrampolineFromCode)(Method*, Method**, Thread*,
-                                                           Runtime::TrampolineType);
-  void (*pUpdateDebuggerFromCode)(void*, void*, int32_t, void*);
-  bool (*pCmplFloat)(float, float);
-  bool (*pCmpgFloat)(float, float);
-  bool (*pCmplDouble)(double, double);
-  bool (*pCmpgDouble)(double, double);
-  int (*pIndexOf)(void*, uint32_t, uint32_t, uint32_t);
-  int (*pStringCompareTo)(void*, void*);
-  int (*pMemcmp16)(void*, void*, int32_t);
+  EntryPoints entrypoints_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(Thread);
diff --git a/src/trace.cc b/src/trace.cc
index 61dd163..c38f017 100644
--- a/src/trace.cc
+++ b/src/trace.cc
@@ -21,12 +21,12 @@
 #include "class_linker.h"
 #include "debugger.h"
 #include "dex_cache.h"
+#include "oat/runtime/oat_support_entrypoints.h"
 #include "object_utils.h"
 #include "os.h"
-#include "runtime_support.h"
 #include "scoped_thread_list_lock.h"
 #include "thread.h"
-
+#include "thread_list.h"
 
 namespace art {
 
@@ -145,10 +145,7 @@
   return true;
 }
 
-#if defined(__arm__)
 static void TraceRestoreStack(Thread* t, void*) {
-  uintptr_t trace_exit = reinterpret_cast<uintptr_t>(art_trace_exit_from_code);
-
   Frame frame = t->GetTopOfStack();
   if (frame.GetSP() != 0) {
     for ( ; frame.GetMethod() != 0; frame.Next()) {
@@ -157,7 +154,7 @@
       }
       uintptr_t pc = frame.GetReturnPC();
       Method* method = frame.GetMethod();
-      if (trace_exit == pc) {
+      if (IsTraceExitPc(pc)) {
         TraceStackFrame trace_frame = t->PopTraceStackFrame();
         frame.SetReturnPC(trace_frame.return_pc_);
         CHECK(method == trace_frame.method_);
@@ -165,11 +162,6 @@
     }
   }
 }
-#else
-static void TraceRestoreStack(Thread*, void*) {
-  UNIMPLEMENTED(WARNING);
-}
-#endif
 
 void Trace::AddSavedCodeToMap(const Method* method, const void* code) {
   saved_code_map_.insert(std::make_pair(method, code));
@@ -189,18 +181,12 @@
   }
 }
 
-#if defined(__arm__)
 void Trace::SaveAndUpdateCode(Method* method) {
-  void* trace_stub = reinterpret_cast<void*>(art_trace_entry_from_code);
+  void* trace_stub = GetLogTraceEntryPoint();
   CHECK(GetSavedCodeFromMap(method) == NULL);
   AddSavedCodeToMap(method, method->GetCode());
   method->SetCode(trace_stub);
 }
-#else
-void Trace::SaveAndUpdateCode(Method*) {
-  UNIMPLEMENTED(WARNING);
-}
-#endif
 
 void Trace::ResetSavedCode(Method* method) {
   CHECK(GetSavedCodeFromMap(method) != NULL);
@@ -445,4 +431,15 @@
   }
 }
 
+uint32_t TraceMethodUnwindFromCode(Thread* self) {
+  Trace* tracer = Runtime::Current()->GetTracer();
+  TraceStackFrame trace_frame = self->PopTraceStackFrame();
+  Method* method = trace_frame.method_;
+  uint32_t lr = trace_frame.return_pc_;
+
+  tracer->LogMethodTraceEvent(self, method, Trace::kMethodTraceUnwind);
+
+  return lr;
+}
+
 }  // namespace art
diff --git a/src/trace.h b/src/trace.h
index d545b14..b0366d9 100644
--- a/src/trace.h
+++ b/src/trace.h
@@ -32,6 +32,8 @@
 class Method;
 class Thread;
 
+uint32_t TraceMethodUnwindFromCode(Thread* self);
+
 struct TraceStackFrame {
   TraceStackFrame(Method* method, uintptr_t return_pc)
       : method_(method), return_pc_(return_pc) {