Portable refactorings.

Separate quick from portable entrypoints.
Move architectural dependencies into arch.

Change-Id: I9adbc0a9782e2959fdc3308215f01e3107632b7c
diff --git a/runtime/Android.mk b/runtime/Android.mk
index bc6a2ed..c686128 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -118,8 +118,6 @@
 	reference_table.cc \
 	reflection.cc \
 	runtime.cc \
-	runtime_support.cc \
-	runtime_support_llvm.cc \
 	signal_catcher.cc \
 	stack.cc \
 	thread.cc \
@@ -143,6 +141,21 @@
 	arch/arm/registers_arm.cc \
 	arch/x86/registers_x86.cc \
 	arch/mips/registers_mips.cc \
+	entrypoints/entrypoint_utils.cc \
+	entrypoints/jni/jni_entrypoints.cc \
+	entrypoints/math_entrypoints.cc \
+	entrypoints/portable/portable_alloc_entrypoints.cc \
+	entrypoints/portable/portable_cast_entrypoints.cc \
+	entrypoints/portable/portable_dexcache_entrypoints.cc \
+	entrypoints/portable/portable_field_entrypoints.cc \
+	entrypoints/portable/portable_fillarray_entrypoints.cc \
+	entrypoints/portable/portable_invoke_entrypoints.cc \
+	entrypoints/portable/portable_jni_entrypoints.cc \
+	entrypoints/portable/portable_lock_entrypoints.cc \
+	entrypoints/portable/portable_proxy_entrypoints.cc \
+	entrypoints/portable/portable_stub_entrypoints.cc \
+	entrypoints/portable/portable_thread_entrypoints.cc \
+	entrypoints/portable/portable_throw_entrypoints.cc \
 	entrypoints/quick/quick_alloc_entrypoints.cc \
 	entrypoints/quick/quick_cast_entrypoints.cc \
 	entrypoints/quick/quick_deoptimization_entrypoints.cc \
@@ -171,39 +184,35 @@
 ifeq ($(TARGET_ARCH),arm)
 LIBART_TARGET_SRC_FILES += \
 	arch/arm/context_arm.cc.arm \
+	arch/arm/entrypoints_init_arm.cc \
+	arch/arm/jni_entrypoints_arm.S \
+	arch/arm/portable_entrypoints_arm.S \
 	arch/arm/quick_entrypoints_arm.S \
-	arch/arm/quick_entrypoints_init_arm.cc
+	arch/arm/thread_arm.cc
 else # TARGET_ARCH != arm
 ifeq ($(TARGET_ARCH),x86)
 LIBART_TARGET_SRC_FILES += \
 	arch/x86/context_x86.cc \
-	arch/x86/quick_entrypoints_init_x86.cc \
-	arch/x86/quick_entrypoints_x86.S
+	arch/x86/entrypoints_init_x86.cc \
+	arch/x86/jni_entrypoints_x86.S \
+	arch/x86/portable_entrypoints_x86.S \
+	arch/x86/quick_entrypoints_x86.S \
+	arch/x86/thread_x86.cc
 else # TARGET_ARCH != x86
 ifeq ($(TARGET_ARCH),mips)
 LIBART_TARGET_SRC_FILES += \
 	arch/mips/context_mips.cc \
-	arch/mips/quick_entrypoints_init_mips.cc \
-	arch/mips/quick_entrypoints_mips.S
+	arch/mips/entrypoints_init_mips.cc \
+	arch/mips/jni_entrypoints_mips.S \
+	arch/mips/portable_entrypoints_mips.S \
+	arch/mips/quick_entrypoints_mips.S \
+	arch/mips/thread_mips.cc
 else # TARGET_ARCH != mips
 $(error unsupported TARGET_ARCH=$(TARGET_ARCH))
 endif # TARGET_ARCH != mips
 endif # TARGET_ARCH != x86
 endif # TARGET_ARCH != arm
 
-ifeq ($(TARGET_ARCH),arm)
-LIBART_TARGET_SRC_FILES += thread_arm.cc
-else # TARGET_ARCH != arm
-ifeq ($(TARGET_ARCH),x86)
-LIBART_TARGET_SRC_FILES += thread_x86.cc
-else # TARGET_ARCH != x86
-ifeq ($(TARGET_ARCH),mips)
-LIBART_TARGET_SRC_FILES += thread_mips.cc
-else # TARGET_ARCH != mips
-$(error unsupported TARGET_ARCH=$(TARGET_ARCH))
-endif # TARGET_ARCH != mips
-endif # TARGET_ARCH != x86
-endif # TARGET_ARCH != arm
 
 LIBART_HOST_SRC_FILES := \
 	$(LIBART_COMMON_SRC_FILES) \
@@ -215,14 +224,11 @@
 ifeq ($(HOST_ARCH),x86)
 LIBART_HOST_SRC_FILES += \
 	arch/x86/context_x86.cc \
-	arch/x86/quick_entrypoints_init_x86.cc \
-	arch/x86/quick_entrypoints_x86.S
-else # HOST_ARCH != x86
-$(error unsupported HOST_ARCH=$(HOST_ARCH))
-endif # HOST_ARCH != x86
-
-ifeq ($(HOST_ARCH),x86)
-LIBART_HOST_SRC_FILES += thread_x86.cc
+	arch/x86/entrypoints_init_x86.cc \
+	arch/x86/jni_entrypoints_x86.S \
+	arch/x86/portable_entrypoints_x86.S \
+	arch/x86/quick_entrypoints_x86.S \
+	arch/x86/thread_x86.cc
 else # HOST_ARCH != x86
 $(error unsupported HOST_ARCH=$(HOST_ARCH))
 endif # HOST_ARCH != x86
diff --git a/runtime/arch/arm/asm_support_arm.S b/runtime/arch/arm/asm_support_arm.S
new file mode 100644
index 0000000..ed655e9
--- /dev/null
+++ b/runtime/arch/arm/asm_support_arm.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
+#define ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
+
+#include "asm_support_arm.h"
+
+.macro ENTRY name
+    .type \name, #function
+    .global \name
+    /* Cache alignment for function entry */
+    .balign 16
+\name:
+    .cfi_startproc
+    .fnstart
+.endm
+
+.macro END name
+    .fnend
+    .cfi_endproc
+    .size \name, .-\name
+.endm
+
+#endif  // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
diff --git a/runtime/arch/arm/asm_support_arm.h b/runtime/arch/arm/asm_support_arm.h
new file mode 100644
index 0000000..ed3d476
--- /dev/null
+++ b/runtime/arch/arm/asm_support_arm.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_ARM_ASM_SUPPORT_ARM_H_
+#define ART_RUNTIME_ARCH_ARM_ASM_SUPPORT_ARM_H_
+
+#include "asm_support.h"
+
+// Register holding suspend check count down.
+#define rSUSPEND r4
+// Register holding Thread::Current().
+#define rSELF r9
+// Offset of field Thread::suspend_count_ verified in InitCpu
+#define THREAD_FLAGS_OFFSET 0
+// Offset of field Thread::exception_ verified in InitCpu
+#define THREAD_EXCEPTION_OFFSET 12
+
+#endif  // ART_RUNTIME_ARCH_ARM_ASM_SUPPORT_ARM_H_
diff --git a/runtime/arch/arm/entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc
new file mode 100644
index 0000000..b71a158
--- /dev/null
+++ b/runtime/arch/arm/entrypoints_init_arm.cc
@@ -0,0 +1,241 @@
+/*
+ * 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 "entrypoints/portable/portable_entrypoints.h"
+#include "entrypoints/quick/quick_entrypoints.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "entrypoints/math_entrypoints.h"
+
+namespace art {
+
+// Alloc entrypoints.
+extern "C" void* art_quick_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_object_from_code(uint32_t type_idx, void* method);
+extern "C" void* art_quick_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
+extern "C" void* art_quick_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_quick_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+
+// Cast entrypoints.
+extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass,
+                                            const mirror::Class* ref_class);
+extern "C" void art_quick_can_put_array_element_from_code(void*, void*);
+extern "C" void art_quick_check_cast_from_code(void*, void*);
+
+// DexCache entrypoints.
+extern "C" void* art_quick_initialize_static_storage_from_code(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_from_code(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_and_verify_access_from_code(uint32_t, void*);
+extern "C" void* art_quick_resolve_string_from_code(void*, uint32_t);
+
+// Exception entrypoints.
+extern "C" void* GetAndClearException(Thread*);
+
+// Field entrypoints.
+extern "C" int art_quick_set32_instance_from_code(uint32_t, void*, int32_t);
+extern "C" int art_quick_set32_static_from_code(uint32_t, int32_t);
+extern "C" int art_quick_set64_instance_from_code(uint32_t, void*, int64_t);
+extern "C" int art_quick_set64_static_from_code(uint32_t, int64_t);
+extern "C" int art_quick_set_obj_instance_from_code(uint32_t, void*, void*);
+extern "C" int art_quick_set_obj_static_from_code(uint32_t, void*);
+extern "C" int32_t art_quick_get32_instance_from_code(uint32_t, void*);
+extern "C" int32_t art_quick_get32_static_from_code(uint32_t);
+extern "C" int64_t art_quick_get64_instance_from_code(uint32_t, void*);
+extern "C" int64_t art_quick_get64_static_from_code(uint32_t);
+extern "C" void* art_quick_get_obj_instance_from_code(uint32_t, void*);
+extern "C" void* art_quick_get_obj_static_from_code(uint32_t);
+
+// FillArray entrypoint.
+extern "C" void art_quick_handle_fill_data_from_code(void*, void*);
+
+// Lock entrypoints.
+extern "C" void art_quick_lock_object_from_code(void*);
+extern "C" void art_quick_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" int32_t __aeabi_f2iz(float op1);        // FLOAT_TO_INT
+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 fmodf(float a, float b);          // REM_FLOAT[_2ADDR]
+
+// Double-precision FP arithmetics.
+extern "C" double fmod(double a, double b);         // REM_DOUBLE[_2ADDR]
+
+// Integer arithmetics.
+extern "C" int __aeabi_idivmod(int32_t, int32_t);  // [DIV|REM]_INT[_2ADDR|_LIT8|_LIT16]
+
+// Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR]
+extern "C" int64_t __aeabi_ldivmod(int64_t, int64_t);
+extern "C" int64_t art_quick_mul_long(int64_t, int64_t);
+extern "C" uint64_t art_quick_shl_long(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_shr_long(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_ushr_long(uint64_t, uint32_t);
+
+// Interpreter entrypoints.
+extern "C" void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
+                                                 const DexFile::CodeItem* code_item,
+                                                 ShadowFrame* shadow_frame, JValue* result);
+extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
+                                           const DexFile::CodeItem* code_item,
+                                           ShadowFrame* shadow_frame, JValue* result);
+
+// Intrinsic entrypoints.
+extern "C" int32_t __memcmp16(void*, void*, int32_t);
+extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
+extern "C" int32_t art_quick_string_compareto(void*, void*);
+
+// Invoke entrypoints.
+extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
+                                                       mirror::Object* receiver,
+                                                       mirror::AbstractMethod** sp, Thread* thread);
+extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
+                                                    mirror::Object* receiver,
+                                                    mirror::AbstractMethod** sp, Thread* thread);
+extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
+extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_static_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_super_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
+
+// Thread entrypoints.
+extern void CheckSuspendFromCode(Thread* thread);
+extern "C" void art_quick_test_suspend();
+
+// Throw entrypoints.
+extern "C" void art_quick_deliver_exception_from_code(void*);
+extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit);
+extern "C" void art_quick_throw_div_zero_from_code();
+extern "C" void art_quick_throw_no_such_method_from_code(int32_t method_idx);
+extern "C" void art_quick_throw_null_pointer_exception_from_code();
+extern "C" void art_quick_throw_stack_overflow_from_code(void*);
+
+void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
+  // Alloc
+  qpoints->pAllocArrayFromCode = art_quick_alloc_array_from_code;
+  qpoints->pAllocArrayFromCodeWithAccessCheck = art_quick_alloc_array_from_code_with_access_check;
+  qpoints->pAllocObjectFromCode = art_quick_alloc_object_from_code;
+  qpoints->pAllocObjectFromCodeWithAccessCheck = art_quick_alloc_object_from_code_with_access_check;
+  qpoints->pCheckAndAllocArrayFromCode = art_quick_check_and_alloc_array_from_code;
+  qpoints->pCheckAndAllocArrayFromCodeWithAccessCheck = art_quick_check_and_alloc_array_from_code_with_access_check;
+
+  // Cast
+  qpoints->pInstanceofNonTrivialFromCode = artIsAssignableFromCode;
+  qpoints->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
+  qpoints->pCheckCastFromCode = art_quick_check_cast_from_code;
+
+  // DexCache
+  qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage_from_code;
+  qpoints->pInitializeTypeAndVerifyAccessFromCode = art_quick_initialize_type_and_verify_access_from_code;
+  qpoints->pInitializeTypeFromCode = art_quick_initialize_type_from_code;
+  qpoints->pResolveStringFromCode = art_quick_resolve_string_from_code;
+
+  // Field
+  qpoints->pSet32Instance = art_quick_set32_instance_from_code;
+  qpoints->pSet32Static = art_quick_set32_static_from_code;
+  qpoints->pSet64Instance = art_quick_set64_instance_from_code;
+  qpoints->pSet64Static = art_quick_set64_static_from_code;
+  qpoints->pSetObjInstance = art_quick_set_obj_instance_from_code;
+  qpoints->pSetObjStatic = art_quick_set_obj_static_from_code;
+  qpoints->pGet32Instance = art_quick_get32_instance_from_code;
+  qpoints->pGet64Instance = art_quick_get64_instance_from_code;
+  qpoints->pGetObjInstance = art_quick_get_obj_instance_from_code;
+  qpoints->pGet32Static = art_quick_get32_static_from_code;
+  qpoints->pGet64Static = art_quick_get64_static_from_code;
+  qpoints->pGetObjStatic = art_quick_get_obj_static_from_code;
+
+  // FillArray
+  qpoints->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
+
+  // JNI
+  qpoints->pJniMethodStart = JniMethodStart;
+  qpoints->pJniMethodStartSynchronized = JniMethodStartSynchronized;
+  qpoints->pJniMethodEnd = JniMethodEnd;
+  qpoints->pJniMethodEndSynchronized = JniMethodEndSynchronized;
+  qpoints->pJniMethodEndWithReference = JniMethodEndWithReference;
+  qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
+
+  // Locks
+  qpoints->pLockObjectFromCode = art_quick_lock_object_from_code;
+  qpoints->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
+
+  // Math
+  qpoints->pCmpgDouble = CmpgDouble;
+  qpoints->pCmpgFloat = CmpgFloat;
+  qpoints->pCmplDouble = CmplDouble;
+  qpoints->pCmplFloat = CmplFloat;
+  qpoints->pFmod = fmod;
+  qpoints->pSqrt = sqrt;
+  qpoints->pL2d = __aeabi_l2d;
+  qpoints->pFmodf = fmodf;
+  qpoints->pL2f = __aeabi_l2f;
+  qpoints->pD2iz = __aeabi_d2iz;
+  qpoints->pF2iz = __aeabi_f2iz;
+  qpoints->pIdivmod = __aeabi_idivmod;
+  qpoints->pD2l = art_d2l;
+  qpoints->pF2l = art_f2l;
+  qpoints->pLdiv = __aeabi_ldivmod;
+  qpoints->pLdivmod = __aeabi_ldivmod;  // result returned in r2:r3
+  qpoints->pLmul = art_quick_mul_long;
+  qpoints->pShlLong = art_quick_shl_long;
+  qpoints->pShrLong = art_quick_shr_long;
+  qpoints->pUshrLong = art_quick_ushr_long;
+
+  // Interpreter
+  qpoints->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
+  qpoints->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
+
+  // Intrinsics
+  qpoints->pIndexOf = art_quick_indexof;
+  qpoints->pMemcmp16 = __memcmp16;
+  qpoints->pStringCompareTo = art_quick_string_compareto;
+  qpoints->pMemcpy = memcpy;
+
+  // Invocation
+  qpoints->pQuickResolutionTrampolineFromCode = artQuickResolutionTrampoline;
+  qpoints->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
+  qpoints->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
+  qpoints->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
+  qpoints->pInvokeStaticTrampolineWithAccessCheck = art_quick_invoke_static_trampoline_with_access_check;
+  qpoints->pInvokeSuperTrampolineWithAccessCheck = art_quick_invoke_super_trampoline_with_access_check;
+  qpoints->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
+
+  // Thread
+  qpoints->pCheckSuspendFromCode = CheckSuspendFromCode;
+  qpoints->pTestSuspendFromCode = art_quick_test_suspend;
+
+  // Throws
+  qpoints->pDeliverException = art_quick_deliver_exception_from_code;
+  qpoints->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code;
+  qpoints->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code;
+  qpoints->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code;
+  qpoints->pThrowNullPointerFromCode = art_quick_throw_null_pointer_exception_from_code;
+  qpoints->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
+
+  // Portable
+  ppoints->pPortableResolutionTrampolineFromCode = artPortableResolutionTrampoline;
+};
+
+}  // namespace art
diff --git a/runtime/arch/arm/jni_entrypoints_arm.S b/runtime/arch/arm/jni_entrypoints_arm.S
new file mode 100644
index 0000000..0a0d06a
--- /dev/null
+++ b/runtime/arch/arm/jni_entrypoints_arm.S
@@ -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 "asm_support_arm.S"
+
+    /*
+     * Jni dlsym lookup stub.
+     */
+    .extern artFindNativeMethod
+ENTRY art_jni_dlsym_lookup_stub
+    push   {r0, r1, r2, r3, lr}           @ spill regs
+    .save  {r0, r1, r2, r3, lr}
+    .pad #20
+    .cfi_adjust_cfa_offset 20
+    sub    sp, #12                        @ pad stack pointer to align frame
+    .pad #12
+    .cfi_adjust_cfa_offset 12
+    mov    r0, r9                         @ pass Thread::Current
+    blx    artFindNativeMethod            @ (Thread*)
+    mov    r12, r0                        @ save result in r12
+    add    sp, #12                        @ restore stack pointer
+    .cfi_adjust_cfa_offset -12
+    pop    {r0, r1, r2, r3, lr}           @ restore regs
+    .cfi_adjust_cfa_offset -20
+    cmp    r12, #0                        @ is method code null?
+    bxne   r12                            @ if non-null, tail call to method's code
+    bx     lr                             @ otherwise, return to caller to handle exception
+END art_jni_dlsym_lookup_stub
+
+    /*
+     * Entry point of native methods when JNI bug compatibility is enabled.
+     */
+    .extern artWorkAroundAppJniBugs
+ENTRY art_quick_work_around_app_jni_bugs
+    @ save registers that may contain arguments and LR that will be crushed by a call
+    push {r0-r3, lr}
+    .save {r0-r3, lr}
+    .cfi_adjust_cfa_offset 16
+    .cfi_rel_offset r0, 0
+    .cfi_rel_offset r1, 4
+    .cfi_rel_offset r2, 8
+    .cfi_rel_offset r3, 12
+    sub sp, #12      @ 3 words of space for alignment
+    mov r0, r9       @ pass Thread::Current
+    mov r1, sp       @ pass SP
+    bl  artWorkAroundAppJniBugs  @ (Thread*, SP)
+    add sp, #12      @ rewind stack
+    mov r12, r0      @ save target address
+    pop {r0-r3, lr}  @ restore possibly modified argument registers
+    .cfi_adjust_cfa_offset -16
+    bx  r12          @ tail call into JNI routine
+END art_quick_work_around_app_jni_bugs
diff --git a/runtime/arch/arm/portable_entrypoints_arm.S b/runtime/arch/arm/portable_entrypoints_arm.S
new file mode 100644
index 0000000..4cc6654
--- /dev/null
+++ b/runtime/arch/arm/portable_entrypoints_arm.S
@@ -0,0 +1,96 @@
+/*
+ * 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 "asm_support_arm.S"
+
+    /*
+     * Portable invocation stub.
+     * On entry:
+     *   r0 = method pointer
+     *   r1 = argument array or NULL for no argument methods
+     *   r2 = size of argument array in bytes
+     *   r3 = (managed) thread pointer
+     *   [sp] = JValue* result
+     *   [sp + 4] = result type char
+     */
+ENTRY art_portable_invoke_stub
+    push   {r0, r4, r5, r9, r11, lr}       @ spill regs
+    .save  {r0, r4, r5, r9, r11, lr}
+    .pad #24
+    .cfi_adjust_cfa_offset 24
+    .cfi_rel_offset r0, 0
+    .cfi_rel_offset r4, 4
+    .cfi_rel_offset r5, 8
+    .cfi_rel_offset r9, 12
+    .cfi_rel_offset r11, 16
+    .cfi_rel_offset lr, 20
+    mov    r11, sp                         @ save the stack pointer
+    .cfi_def_cfa_register r11
+    mov    r9, r3                          @ move managed thread pointer into r9
+    mov    r4, #SUSPEND_CHECK_INTERVAL     @ reset r4 to suspend check interval
+    add    r5, r2, #16                     @ create space for method pointer in frame
+    and    r5, #0xFFFFFFF0                 @ align frame size to 16 bytes
+    sub    sp, r5                          @ reserve stack space for argument array
+    add    r0, sp, #4                      @ pass stack pointer + method ptr as dest for memcpy
+    bl     memcpy                          @ memcpy (dest, src, bytes)
+    ldr    r0, [r11]                       @ restore method*
+    ldr    r1, [sp, #4]                    @ copy arg value for r1
+    ldr    r2, [sp, #8]                    @ copy arg value for r2
+    ldr    r3, [sp, #12]                   @ copy arg value for r3
+    mov    ip, #0                          @ set ip to 0
+    str    ip, [sp]                        @ store NULL for method* at bottom of frame
+    add    sp, #16                         @ first 4 args are not passed on stack for portable
+    ldr    ip, [r0, #METHOD_CODE_OFFSET]   @ get pointer to the code
+    blx    ip                              @ call the method
+    mov    sp, r11                         @ restore the stack pointer
+    ldr    ip, [sp, #24]                   @ load the result pointer
+    strd   r0, [ip]                        @ store r0/r1 into result pointer
+    pop    {r0, r4, r5, r9, r11, lr}       @ restore spill regs
+    .cfi_adjust_cfa_offset -24
+    bx     lr
+END art_portable_invoke_stub
+
+    .extern artPortableProxyInvokeHandler
+ENTRY art_portable_proxy_invoke_handler
+    @ Fake callee save ref and args frame set up, note portable doesn't use callee save frames.
+    @ TODO: just save the registers that are needed in artPortableProxyInvokeHandler.
+    push {r1-r3, r5-r8, r10-r11, lr}  @ 10 words of callee saves
+    .save {r1-r3, r5-r8, r10-r11, lr}
+    .cfi_adjust_cfa_offset 40
+    .cfi_rel_offset r1, 0
+    .cfi_rel_offset r2, 4
+    .cfi_rel_offset r3, 8
+    .cfi_rel_offset r5, 12
+    .cfi_rel_offset r6, 16
+    .cfi_rel_offset r7, 20
+    .cfi_rel_offset r8, 24
+    .cfi_rel_offset r10, 28
+    .cfi_rel_offset r11, 32
+    .cfi_rel_offset lr, 36
+    sub sp, #8                        @ 2 words of space, bottom word will hold Method*
+    .pad #8
+    .cfi_adjust_cfa_offset 8
+    @ Begin argument set up.
+    str     r0, [sp, #0]           @ place proxy method at bottom of frame
+    mov     r2, r9                 @ pass Thread::Current
+    mov     r3, sp                 @ pass SP
+    blx     artPortableProxyInvokeHandler  @ (Method* proxy method, receiver, Thread*, SP)
+    ldr     r12, [r9, #THREAD_EXCEPTION_OFFSET]  @ load Thread::Current()->exception_
+    ldr     lr,  [sp, #44]         @ restore lr
+    add     sp,  #48               @ pop frame
+    .cfi_adjust_cfa_offset -48
+    bx      lr                     @ return
+END art_portable_proxy_invoke_handler
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index f19e8ba..9b8d238 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -14,29 +14,13 @@
  * limitations under the License.
  */
 
-#include "asm_support.h"
+#include "asm_support_arm.S"
 
     /* Deliver the given exception */
     .extern artDeliverExceptionFromCode
     /* Deliver an exception pending on a thread */
     .extern artDeliverPendingException
 
-.macro ENTRY name
-    .type \name, #function
-    .global \name
-    /* Cache alignment for function entry */
-    .balign 16
-\name:
-    .cfi_startproc
-    .fnstart
-.endm
-
-.macro END name
-    .fnend
-    .cfi_endproc
-    .size \name, .-\name
-.endm
-
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveAll)
@@ -247,53 +231,6 @@
 INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
 
     /*
-     * Portable invocation stub.
-     * On entry:
-     *   r0 = method pointer
-     *   r1 = argument array or NULL for no argument methods
-     *   r2 = size of argument array in bytes
-     *   r3 = (managed) thread pointer
-     *   [sp] = JValue* result
-     *   [sp + 4] = result type char
-     */
-ENTRY art_portable_invoke_stub
-    push   {r0, r4, r5, r9, r11, lr}       @ spill regs
-    .save  {r0, r4, r5, r9, r11, lr}
-    .pad #24
-    .cfi_adjust_cfa_offset 24
-    .cfi_rel_offset r0, 0
-    .cfi_rel_offset r4, 4
-    .cfi_rel_offset r5, 8
-    .cfi_rel_offset r9, 12
-    .cfi_rel_offset r11, 16
-    .cfi_rel_offset lr, 20
-    mov    r11, sp                         @ save the stack pointer
-    .cfi_def_cfa_register r11
-    mov    r9, r3                          @ move managed thread pointer into r9
-    mov    r4, #SUSPEND_CHECK_INTERVAL     @ reset r4 to suspend check interval
-    add    r5, r2, #16                     @ create space for method pointer in frame
-    and    r5, #0xFFFFFFF0                 @ align frame size to 16 bytes
-    sub    sp, r5                          @ reserve stack space for argument array
-    add    r0, sp, #4                      @ pass stack pointer + method ptr as dest for memcpy
-    bl     memcpy                          @ memcpy (dest, src, bytes)
-    ldr    r0, [r11]                       @ restore method*
-    ldr    r1, [sp, #4]                    @ copy arg value for r1
-    ldr    r2, [sp, #8]                    @ copy arg value for r2
-    ldr    r3, [sp, #12]                   @ copy arg value for r3
-    mov    ip, #0                          @ set ip to 0
-    str    ip, [sp]                        @ store NULL for method* at bottom of frame
-    add    sp, #16                         @ first 4 args are not passed on stack for portable
-    ldr    ip, [r0, #METHOD_CODE_OFFSET]   @ get pointer to the code
-    blx    ip                              @ call the method
-    mov    sp, r11                         @ restore the stack pointer
-    ldr    ip, [sp, #24]                   @ load the result pointer
-    strd   r0, [ip]                        @ store r0/r1 into result pointer
-    pop    {r0, r4, r5, r9, r11, lr}       @ restore spill regs
-    .cfi_adjust_cfa_offset -24
-    bx     lr
-END art_portable_invoke_stub
-
-    /*
      * Quick invocation stub.
      * On entry:
      *   r0 = method pointer
@@ -353,30 +290,6 @@
 END art_quick_do_long_jump
 
     /*
-     * Entry point of native methods when JNI bug compatibility is enabled.
-     */
-    .extern artWorkAroundAppJniBugs
-ENTRY art_quick_work_around_app_jni_bugs
-    @ save registers that may contain arguments and LR that will be crushed by a call
-    push {r0-r3, lr}
-    .save {r0-r3, lr}
-    .cfi_adjust_cfa_offset 16
-    .cfi_rel_offset r0, 0
-    .cfi_rel_offset r1, 4
-    .cfi_rel_offset r2, 8
-    .cfi_rel_offset r3, 12
-    sub sp, #12      @ 3 words of space for alignment
-    mov r0, r9       @ pass Thread::Current
-    mov r1, sp       @ pass SP
-    bl  artWorkAroundAppJniBugs  @ (Thread*, SP)
-    add sp, #12      @ rewind stack
-    mov r12, r0      @ save target address
-    pop {r0-r3, lr}  @ restore possibly modified argument registers
-    .cfi_adjust_cfa_offset -16
-    bx  r12          @ tail call into JNI routine
-END art_quick_work_around_app_jni_bugs
-
-    /*
      * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
      * failure.
      */
@@ -906,20 +819,6 @@
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
 END art_quick_test_suspend
 
-    .extern artPortableProxyInvokeHandler
-ENTRY art_portable_proxy_invoke_handler
-    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
-    str     r0, [sp, #0]           @ place proxy method at bottom of frame
-    mov     r2, r9                 @ pass Thread::Current
-    mov     r3, sp                 @ pass SP
-    blx     artPortableProxyInvokeHandler  @ (Method* proxy method, receiver, Thread*, SP)
-    ldr     r12, [r9, #THREAD_EXCEPTION_OFFSET]  @ load Thread::Current()->exception_
-    ldr     lr,  [sp, #44]         @ restore lr
-    add     sp,  #48               @ pop frame
-    .cfi_adjust_cfa_offset -48
-    bx      lr                     @ return
-END art_portable_proxy_invoke_handler
-
     /*
      * Called by managed code that is attempting to call a method on a proxy class. On entry
      * r0 holds the proxy method and r1 holds the receiver; r2 and r3 may contain arguments. The
@@ -1045,30 +944,6 @@
 END art_quick_abstract_method_error_stub
 
     /*
-     * Jni dlsym lookup stub.
-     */
-    .extern artFindNativeMethod
-ENTRY art_jni_dlsym_lookup_stub
-    push   {r0, r1, r2, r3, lr}           @ spill regs
-    .save  {r0, r1, r2, r3, lr}
-    .pad #20
-    .cfi_adjust_cfa_offset 20
-    sub    sp, #12                        @ pad stack pointer to align frame
-    .pad #12
-    .cfi_adjust_cfa_offset 12
-    mov    r0, r9                         @ pass Thread::Current
-    blx    artFindNativeMethod            @ (Thread*)
-    mov    r12, r0                        @ save result in r12
-    add    sp, #12                        @ restore stack pointer
-    .cfi_adjust_cfa_offset -12
-    pop    {r0, r1, r2, r3, lr}           @ restore regs
-    .cfi_adjust_cfa_offset -20
-    cmp    r12, #0                        @ is method code null?
-    bxne   r12                            @ if non-null, tail call to method's code
-    bx     lr                             @ otherwise, return to caller to handle exception
-END art_jni_dlsym_lookup_stub
-
-    /*
      * Signed 64-bit integer multiply.
      *
      * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
diff --git a/runtime/arch/arm/quick_entrypoints_init_arm.cc b/runtime/arch/arm/quick_entrypoints_init_arm.cc
deleted file mode 100644
index 2f66b36..0000000
--- a/runtime/arch/arm/quick_entrypoints_init_arm.cc
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "runtime_support.h"
-
-namespace art {
-
-// Alloc entrypoints.
-extern "C" void* art_quick_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_object_from_code(uint32_t type_idx, void* method);
-extern "C" void* art_quick_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
-extern "C" void* art_quick_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-
-// Cast entrypoints.
-extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass,
-                                            const mirror::Class* ref_class);
-extern "C" void art_quick_can_put_array_element_from_code(void*, void*);
-extern "C" void art_quick_check_cast_from_code(void*, void*);
-
-// DexCache entrypoints.
-extern "C" void* art_quick_initialize_static_storage_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_and_verify_access_from_code(uint32_t, void*);
-extern "C" void* art_quick_resolve_string_from_code(void*, uint32_t);
-
-// Exception entrypoints.
-extern "C" void* GetAndClearException(Thread*);
-
-// Field entrypoints.
-extern "C" int art_quick_set32_instance_from_code(uint32_t, void*, int32_t);
-extern "C" int art_quick_set32_static_from_code(uint32_t, int32_t);
-extern "C" int art_quick_set64_instance_from_code(uint32_t, void*, int64_t);
-extern "C" int art_quick_set64_static_from_code(uint32_t, int64_t);
-extern "C" int art_quick_set_obj_instance_from_code(uint32_t, void*, void*);
-extern "C" int art_quick_set_obj_static_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_instance_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_static_from_code(uint32_t);
-extern "C" int64_t art_quick_get64_instance_from_code(uint32_t, void*);
-extern "C" int64_t art_quick_get64_static_from_code(uint32_t);
-extern "C" void* art_quick_get_obj_instance_from_code(uint32_t, void*);
-extern "C" void* art_quick_get_obj_static_from_code(uint32_t);
-
-// FillArray entrypoint.
-extern "C" void art_quick_handle_fill_data_from_code(void*, void*);
-
-// Lock entrypoints.
-extern "C" void art_quick_lock_object_from_code(void*);
-extern "C" void art_quick_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" int32_t __aeabi_f2iz(float op1);        // FLOAT_TO_INT
-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 fmodf(float a, float b);          // REM_FLOAT[_2ADDR]
-
-// Double-precision FP arithmetics.
-extern "C" double fmod(double a, double b);         // REM_DOUBLE[_2ADDR]
-
-// Integer arithmetics.
-extern "C" int __aeabi_idivmod(int32_t, int32_t);  // [DIV|REM]_INT[_2ADDR|_LIT8|_LIT16]
-
-// Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR]
-extern "C" int64_t __aeabi_ldivmod(int64_t, int64_t);
-extern "C" int64_t art_quick_mul_long(int64_t, int64_t);
-extern "C" uint64_t art_quick_shl_long(uint64_t, uint32_t);
-extern "C" uint64_t art_quick_shr_long(uint64_t, uint32_t);
-extern "C" uint64_t art_quick_ushr_long(uint64_t, uint32_t);
-
-// Interpreter entrypoints.
-extern "C" void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
-                                                 const DexFile::CodeItem* code_item,
-                                                 ShadowFrame* shadow_frame, JValue* result);
-extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
-                                           const DexFile::CodeItem* code_item,
-                                           ShadowFrame* shadow_frame, JValue* result);
-
-// Intrinsic entrypoints.
-extern "C" int32_t __memcmp16(void*, void*, int32_t);
-extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
-extern "C" int32_t art_quick_string_compareto(void*, void*);
-
-// Invoke entrypoints.
-extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
-                                                       mirror::Object* receiver,
-                                                       mirror::AbstractMethod** sp, Thread* thread);
-extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
-                                                    mirror::Object* receiver,
-                                                    mirror::AbstractMethod** sp, Thread* thread);
-extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
-extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_static_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_super_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
-
-// Thread entrypoints.
-extern void CheckSuspendFromCode(Thread* thread);
-extern "C" void art_quick_test_suspend();
-
-// Throw entrypoints.
-extern "C" void art_quick_deliver_exception_from_code(void*);
-extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit);
-extern "C" void art_quick_throw_div_zero_from_code();
-extern "C" void art_quick_throw_no_such_method_from_code(int32_t method_idx);
-extern "C" void art_quick_throw_null_pointer_exception_from_code();
-extern "C" void art_quick_throw_stack_overflow_from_code(void*);
-
-void InitEntryPoints(QuickEntryPoints* points) {
-  // Alloc
-  points->pAllocArrayFromCode = art_quick_alloc_array_from_code;
-  points->pAllocArrayFromCodeWithAccessCheck = art_quick_alloc_array_from_code_with_access_check;
-  points->pAllocObjectFromCode = art_quick_alloc_object_from_code;
-  points->pAllocObjectFromCodeWithAccessCheck = art_quick_alloc_object_from_code_with_access_check;
-  points->pCheckAndAllocArrayFromCode = art_quick_check_and_alloc_array_from_code;
-  points->pCheckAndAllocArrayFromCodeWithAccessCheck = art_quick_check_and_alloc_array_from_code_with_access_check;
-
-  // Cast
-  points->pInstanceofNonTrivialFromCode = artIsAssignableFromCode;
-  points->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
-  points->pCheckCastFromCode = art_quick_check_cast_from_code;
-
-  // DexCache
-  points->pInitializeStaticStorage = art_quick_initialize_static_storage_from_code;
-  points->pInitializeTypeAndVerifyAccessFromCode = art_quick_initialize_type_and_verify_access_from_code;
-  points->pInitializeTypeFromCode = art_quick_initialize_type_from_code;
-  points->pResolveStringFromCode = art_quick_resolve_string_from_code;
-
-  // Field
-  points->pSet32Instance = art_quick_set32_instance_from_code;
-  points->pSet32Static = art_quick_set32_static_from_code;
-  points->pSet64Instance = art_quick_set64_instance_from_code;
-  points->pSet64Static = art_quick_set64_static_from_code;
-  points->pSetObjInstance = art_quick_set_obj_instance_from_code;
-  points->pSetObjStatic = art_quick_set_obj_static_from_code;
-  points->pGet32Instance = art_quick_get32_instance_from_code;
-  points->pGet64Instance = art_quick_get64_instance_from_code;
-  points->pGetObjInstance = art_quick_get_obj_instance_from_code;
-  points->pGet32Static = art_quick_get32_static_from_code;
-  points->pGet64Static = art_quick_get64_static_from_code;
-  points->pGetObjStatic = art_quick_get_obj_static_from_code;
-
-  // FillArray
-  points->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
-
-  // JNI
-  points->pJniMethodStart = JniMethodStart;
-  points->pJniMethodStartSynchronized = JniMethodStartSynchronized;
-  points->pJniMethodEnd = JniMethodEnd;
-  points->pJniMethodEndSynchronized = JniMethodEndSynchronized;
-  points->pJniMethodEndWithReference = JniMethodEndWithReference;
-  points->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
-
-  // Locks
-  points->pLockObjectFromCode = art_quick_lock_object_from_code;
-  points->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
-
-  // Math
-  points->pCmpgDouble = CmpgDouble;
-  points->pCmpgFloat = CmpgFloat;
-  points->pCmplDouble = CmplDouble;
-  points->pCmplFloat = CmplFloat;
-  points->pFmod = fmod;
-  points->pSqrt = sqrt;
-  points->pL2d = __aeabi_l2d;
-  points->pFmodf = fmodf;
-  points->pL2f = __aeabi_l2f;
-  points->pD2iz = __aeabi_d2iz;
-  points->pF2iz = __aeabi_f2iz;
-  points->pIdivmod = __aeabi_idivmod;
-  points->pD2l = art_d2l;
-  points->pF2l = art_f2l;
-  points->pLdiv = __aeabi_ldivmod;
-  points->pLdivmod = __aeabi_ldivmod;  // result returned in r2:r3
-  points->pLmul = art_quick_mul_long;
-  points->pShlLong = art_quick_shl_long;
-  points->pShrLong = art_quick_shr_long;
-  points->pUshrLong = art_quick_ushr_long;
-
-  // Interpreter
-  points->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
-  points->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
-
-  // Intrinsics
-  points->pIndexOf = art_quick_indexof;
-  points->pMemcmp16 = __memcmp16;
-  points->pStringCompareTo = art_quick_string_compareto;
-  points->pMemcpy = memcpy;
-
-  // Invocation
-  points->pPortableResolutionTrampolineFromCode = artPortableResolutionTrampoline;
-  points->pQuickResolutionTrampolineFromCode = artQuickResolutionTrampoline;
-  points->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
-  points->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
-  points->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
-  points->pInvokeStaticTrampolineWithAccessCheck = art_quick_invoke_static_trampoline_with_access_check;
-  points->pInvokeSuperTrampolineWithAccessCheck = art_quick_invoke_super_trampoline_with_access_check;
-  points->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
-
-  // Thread
-  points->pCheckSuspendFromCode = CheckSuspendFromCode;
-  points->pTestSuspendFromCode = art_quick_test_suspend;
-
-  // Throws
-  points->pDeliverException = art_quick_deliver_exception_from_code;
-  points->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code;
-  points->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code;
-  points->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code;
-  points->pThrowNullPointerFromCode = art_quick_throw_null_pointer_exception_from_code;
-  points->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
-};
-
-}  // namespace art
diff --git a/runtime/thread_arm.cc b/runtime/arch/arm/thread_arm.cc
similarity index 93%
copy from runtime/thread_arm.cc
copy to runtime/arch/arm/thread_arm.cc
index 0ef26bf..ea908be 100644
--- a/runtime/thread_arm.cc
+++ b/runtime/arch/arm/thread_arm.cc
@@ -16,8 +16,8 @@
 
 #include "thread.h"
 
-#include "asm_support.h"
-#include "base/macros.h"
+#include "asm_support_arm.h"
+#include "base/logging.h"
 
 namespace art {
 
diff --git a/runtime/arch/mips/asm_support_mips.S b/runtime/arch/mips/asm_support_mips.S
new file mode 100644
index 0000000..8a34b9d
--- /dev/null
+++ b/runtime/arch/mips/asm_support_mips.S
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_S_
+#define ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_S_
+
+#include "asm_support_mips.h"
+
+    /* Cache alignment for function entry */
+.macro ENTRY name
+    .type \name, %function
+    .global \name
+    .balign 16
+\name:
+    .cfi_startproc
+.endm
+
+.macro END name
+    .cfi_endproc
+    .size \name, .-\name
+.endm
+
+    /* Generates $gp for function calls */
+.macro GENERATE_GLOBAL_POINTER
+    .cpload $t9
+.endm
+
+#endif  // ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_S_
diff --git a/runtime/arch/mips/asm_support_mips.h b/runtime/arch/mips/asm_support_mips.h
new file mode 100644
index 0000000..9a66352
--- /dev/null
+++ b/runtime/arch/mips/asm_support_mips.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_H_
+#define ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_H_
+
+#include "asm_support.h"
+
+// Register holding suspend check count down.
+#define rSUSPEND $s0
+// Register holding Thread::Current().
+#define rSELF $s1
+// Offset of field Thread::suspend_count_ verified in InitCpu
+#define THREAD_FLAGS_OFFSET 0
+// Offset of field Thread::exception_ verified in InitCpu
+#define THREAD_EXCEPTION_OFFSET 12
+
+#endif  // ART_RUNTIME_ARCH_MIPS_ASM_SUPPORT_MIPS_H_
diff --git a/runtime/arch/mips/entrypoints_init_mips.cc b/runtime/arch/mips/entrypoints_init_mips.cc
new file mode 100644
index 0000000..0a62a40
--- /dev/null
+++ b/runtime/arch/mips/entrypoints_init_mips.cc
@@ -0,0 +1,242 @@
+/*
+ * 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 "entrypoints/portable/portable_entrypoints.h"
+#include "entrypoints/quick/quick_entrypoints.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "entrypoints/math_entrypoints.h"
+
+namespace art {
+
+// Alloc entrypoints.
+extern "C" void* art_quick_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_object_from_code(uint32_t type_idx, void* method);
+extern "C" void* art_quick_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
+extern "C" void* art_quick_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_quick_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+
+// Cast entrypoints.
+extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass,
+                                            const mirror::Class* ref_class);
+extern "C" void art_quick_can_put_array_element_from_code(void*, void*);
+extern "C" void art_quick_check_cast_from_code(void*, void*);
+
+// DexCache entrypoints.
+extern "C" void* art_quick_initialize_static_storage_from_code(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_from_code(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_and_verify_access_from_code(uint32_t, void*);
+extern "C" void* art_quick_resolve_string_from_code(void*, uint32_t);
+
+// Exception entrypoints.
+extern "C" void* GetAndClearException(Thread*);
+
+// Field entrypoints.
+extern "C" int art_quick_set32_instance_from_code(uint32_t, void*, int32_t);
+extern "C" int art_quick_set32_static_from_code(uint32_t, int32_t);
+extern "C" int art_quick_set64_instance_from_code(uint32_t, void*, int64_t);
+extern "C" int art_quick_set64_static_from_code(uint32_t, int64_t);
+extern "C" int art_quick_set_obj_instance_from_code(uint32_t, void*, void*);
+extern "C" int art_quick_set_obj_static_from_code(uint32_t, void*);
+extern "C" int32_t art_quick_get32_instance_from_code(uint32_t, void*);
+extern "C" int32_t art_quick_get32_static_from_code(uint32_t);
+extern "C" int64_t art_quick_get64_instance_from_code(uint32_t, void*);
+extern "C" int64_t art_quick_get64_static_from_code(uint32_t);
+extern "C" void* art_quick_get_obj_instance_from_code(uint32_t, void*);
+extern "C" void* art_quick_get_obj_static_from_code(uint32_t);
+
+// FillArray entrypoint.
+extern "C" void art_quick_handle_fill_data_from_code(void*, void*);
+
+// Lock entrypoints.
+extern "C" void art_quick_lock_object_from_code(void*);
+extern "C" void art_quick_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 "C" int64_t artLmulFromCode(int64_t a, int64_t b);
+extern "C" int64_t artLdivFromCode(int64_t a, int64_t b);
+extern "C" int64_t artLdivmodFromCode(int64_t a, int64_t b);
+
+// Math conversions.
+extern "C" int32_t __fixsfsi(float op1);      // FLOAT_TO_INT
+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 fmodf(float a, float b);      // REM_FLOAT[_2ADDR]
+
+// Double-precision FP arithmetics.
+extern "C" double fmod(double a, double b);     // REM_DOUBLE[_2ADDR]
+
+// Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR]
+extern "C" int64_t __divdi3(int64_t, int64_t);
+extern "C" int64_t __moddi3(int64_t, int64_t);
+extern "C" uint64_t art_quick_shl_long(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_shr_long(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_ushr_long(uint64_t, uint32_t);
+
+// Interpreter entrypoints.
+extern "C" void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
+                                                 const DexFile::CodeItem* code_item,
+                                                 ShadowFrame* shadow_frame, JValue* result);
+extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
+                                           const DexFile::CodeItem* code_item,
+                                           ShadowFrame* shadow_frame, JValue* result);
+
+// Intrinsic entrypoints.
+extern "C" int32_t __memcmp16(void*, void*, int32_t);
+extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
+extern "C" int32_t art_quick_string_compareto(void*, void*);
+
+// Invoke entrypoints.
+extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
+                                                       mirror::Object* receiver,
+                                                       mirror::AbstractMethod** sp, Thread* thread);
+extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
+                                                    mirror::Object* receiver,
+                                                    mirror::AbstractMethod** sp, Thread* thread);
+extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
+extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_static_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_super_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
+
+// Thread entrypoints.
+extern void CheckSuspendFromCode(Thread* thread);
+extern "C" void art_quick_test_suspend();
+
+// Throw entrypoints.
+extern "C" void art_quick_deliver_exception_from_code(void*);
+extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit);
+extern "C" void art_quick_throw_div_zero_from_code();
+extern "C" void art_quick_throw_no_such_method_from_code(int32_t method_idx);
+extern "C" void art_quick_throw_null_pointer_exception_from_code();
+extern "C" void art_quick_throw_stack_overflow_from_code(void*);
+
+void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
+  // Alloc
+  qpoints->pAllocArrayFromCode = art_quick_alloc_array_from_code;
+  qpoints->pAllocArrayFromCodeWithAccessCheck = art_quick_alloc_array_from_code_with_access_check;
+  qpoints->pAllocObjectFromCode = art_quick_alloc_object_from_code;
+  qpoints->pAllocObjectFromCodeWithAccessCheck = art_quick_alloc_object_from_code_with_access_check;
+  qpoints->pCheckAndAllocArrayFromCode = art_quick_check_and_alloc_array_from_code;
+  qpoints->pCheckAndAllocArrayFromCodeWithAccessCheck = art_quick_check_and_alloc_array_from_code_with_access_check;
+
+  // Cast
+  qpoints->pInstanceofNonTrivialFromCode = artIsAssignableFromCode;
+  qpoints->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
+  qpoints->pCheckCastFromCode = art_quick_check_cast_from_code;
+
+  // DexCache
+  qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage_from_code;
+  qpoints->pInitializeTypeAndVerifyAccessFromCode = art_quick_initialize_type_and_verify_access_from_code;
+  qpoints->pInitializeTypeFromCode = art_quick_initialize_type_from_code;
+  qpoints->pResolveStringFromCode = art_quick_resolve_string_from_code;
+
+  // Field
+  qpoints->pSet32Instance = art_quick_set32_instance_from_code;
+  qpoints->pSet32Static = art_quick_set32_static_from_code;
+  qpoints->pSet64Instance = art_quick_set64_instance_from_code;
+  qpoints->pSet64Static = art_quick_set64_static_from_code;
+  qpoints->pSetObjInstance = art_quick_set_obj_instance_from_code;
+  qpoints->pSetObjStatic = art_quick_set_obj_static_from_code;
+  qpoints->pGet32Instance = art_quick_get32_instance_from_code;
+  qpoints->pGet64Instance = art_quick_get64_instance_from_code;
+  qpoints->pGetObjInstance = art_quick_get_obj_instance_from_code;
+  qpoints->pGet32Static = art_quick_get32_static_from_code;
+  qpoints->pGet64Static = art_quick_get64_static_from_code;
+  qpoints->pGetObjStatic = art_quick_get_obj_static_from_code;
+
+  // FillArray
+  qpoints->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
+
+  // JNI
+  qpoints->pJniMethodStart = JniMethodStart;
+  qpoints->pJniMethodStartSynchronized = JniMethodStartSynchronized;
+  qpoints->pJniMethodEnd = JniMethodEnd;
+  qpoints->pJniMethodEndSynchronized = JniMethodEndSynchronized;
+  qpoints->pJniMethodEndWithReference = JniMethodEndWithReference;
+  qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
+
+  // Locks
+  qpoints->pLockObjectFromCode = art_quick_lock_object_from_code;
+  qpoints->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
+
+  // Math
+  qpoints->pCmpgDouble = CmpgDouble;
+  qpoints->pCmpgFloat = CmpgFloat;
+  qpoints->pCmplDouble = CmplDouble;
+  qpoints->pCmplFloat = CmplFloat;
+  qpoints->pFmod = fmod;
+  qpoints->pL2d = __floatdidf;
+  qpoints->pFmodf = fmodf;
+  qpoints->pL2f = __floatdisf;
+  qpoints->pD2iz = __fixdfsi;
+  qpoints->pF2iz = __fixsfsi;
+  qpoints->pIdivmod = NULL;
+  qpoints->pD2l = art_d2l;
+  qpoints->pF2l = art_f2l;
+  qpoints->pLdiv = artLdivFromCode;
+  qpoints->pLdivmod = artLdivmodFromCode;
+  qpoints->pLmul = artLmulFromCode;
+  qpoints->pShlLong = art_quick_shl_long;
+  qpoints->pShrLong = art_quick_shr_long;
+  qpoints->pUshrLong = art_quick_ushr_long;
+
+  // Interpreter
+  qpoints->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
+  qpoints->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
+
+  // Intrinsics
+  qpoints->pIndexOf = art_quick_indexof;
+  qpoints->pMemcmp16 = __memcmp16;
+  qpoints->pStringCompareTo = art_quick_string_compareto;
+  qpoints->pMemcpy = memcpy;
+
+  // Invocation
+  qpoints->pQuickResolutionTrampolineFromCode = artQuickResolutionTrampoline;
+  qpoints->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
+  qpoints->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
+  qpoints->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
+  qpoints->pInvokeStaticTrampolineWithAccessCheck = art_quick_invoke_static_trampoline_with_access_check;
+  qpoints->pInvokeSuperTrampolineWithAccessCheck = art_quick_invoke_super_trampoline_with_access_check;
+  qpoints->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
+
+  // Thread
+  qpoints->pCheckSuspendFromCode = CheckSuspendFromCode;
+  qpoints->pTestSuspendFromCode = art_quick_test_suspend;
+
+  // Throws
+  qpoints->pDeliverException = art_quick_deliver_exception_from_code;
+  qpoints->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code;
+  qpoints->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code;
+  qpoints->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code;
+  qpoints->pThrowNullPointerFromCode = art_quick_throw_null_pointer_exception_from_code;
+  qpoints->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
+
+  // Portable
+  ppoints->pPortableResolutionTrampolineFromCode = artPortableResolutionTrampoline;
+};
+
+}  // namespace art
diff --git a/runtime/arch/mips/jni_entrypoints_mips.S b/runtime/arch/mips/jni_entrypoints_mips.S
new file mode 100644
index 0000000..fca6d77
--- /dev/null
+++ b/runtime/arch/mips/jni_entrypoints_mips.S
@@ -0,0 +1,89 @@
+/*
+ * 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 "asm_support_mips.S"
+
+    .set noreorder
+    .balign 4
+
+    /*
+     * Jni dlsym lookup stub.
+     */
+    .extern artFindNativeMethod
+ENTRY art_jni_dlsym_lookup_stub
+    GENERATE_GLOBAL_POINTER
+    addiu $sp, $sp, -32          # leave room for $a0, $a1, $a2, $a3, and $ra
+    .cfi_adjust_cfa_offset 32
+    sw     $ra, 16($sp)
+    .cfi_rel_offset 31, 16
+    sw     $a3, 12($sp)
+    .cfi_rel_offset 7, 12
+    sw     $a2, 8($sp)
+    .cfi_rel_offset 6, 8
+    sw     $a1, 4($sp)
+    .cfi_rel_offset 5, 4
+    sw     $a0, 0($sp)
+    .cfi_rel_offset 4, 0
+    jal   artFindNativeMethod   # (Thread*)
+    move  $a0, $s1              # pass Thread::Current()
+    lw    $a0, 0($sp)           # restore registers from stack
+    lw    $a1, 4($sp)
+    lw    $a2, 8($sp)
+    lw    $a3, 12($sp)
+    lw    $ra, 16($sp)
+    beq   $v0, $zero, no_native_code_found
+    addiu $sp, $sp, 32          # restore the stack
+    .cfi_adjust_cfa_offset -32
+    move  $t9, $v0              # put method code result in $t9
+    jr    $t9                   # leaf call to method's code
+    nop
+no_native_code_found:
+    jr    $ra
+    nop
+END art_jni_dlsym_lookup_stub
+
+    /*
+     * Entry point of native methods when JNI bug compatibility is enabled.
+     */
+    .extern artWorkAroundAppJniBugs
+ENTRY art_quick_work_around_app_jni_bugs
+    GENERATE_GLOBAL_POINTER
+    # save registers that may contain arguments and LR that will be crushed by a call
+    addiu    $sp, $sp, -32
+    .cfi_adjust_cfa_offset 32
+    sw       $ra, 28($sp)
+    .cfi_rel_offset 31, 28
+    sw       $a3, 24($sp)
+    .cfi_rel_offset 7, 28
+    sw       $a2, 20($sp)
+    .cfi_rel_offset 6, 28
+    sw       $a1, 16($sp)
+    .cfi_rel_offset 5, 28
+    sw       $a0, 12($sp)
+    .cfi_rel_offset 4, 28
+    move     $a0, rSELF       # pass Thread::Current
+    jal      artWorkAroundAppJniBugs  # (Thread*, $sp)
+    move     $a1, $sp         # pass $sp
+    move     $t9, $v0         # save target address
+    lw       $a0, 12($sp)
+    lw       $a1, 16($sp)
+    lw       $a2, 20($sp)
+    lw       $a3, 24($sp)
+    lw       $ra, 28($sp)
+    jr       $t9              # tail call into JNI routine
+    addiu    $sp, $sp, 32
+    .cfi_adjust_cfa_offset -32
+END art_quick_work_around_app_jni_bugs
diff --git a/runtime/arch/mips/portable_entrypoints_mips.S b/runtime/arch/mips/portable_entrypoints_mips.S
new file mode 100644
index 0000000..e7a9b0f
--- /dev/null
+++ b/runtime/arch/mips/portable_entrypoints_mips.S
@@ -0,0 +1,73 @@
+/*
+ * 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 "asm_support_mips.S"
+
+    .set noreorder
+    .balign 4
+
+    .extern artPortableProxyInvokeHandler
+ENTRY art_portable_proxy_invoke_handler
+    GENERATE_GLOBAL_POINTER
+    # Fake callee save ref and args frame set up, note portable doesn't use callee save frames.
+    # TODO: just save the registers that are needed in artPortableProxyInvokeHandler.
+    addiu  $sp, $sp, -64
+    .cfi_adjust_cfa_offset 64
+    sw     $ra, 60($sp)
+    .cfi_rel_offset 31, 60
+    sw     $s8, 56($sp)
+    .cfi_rel_offset 30, 56
+    sw     $gp, 52($sp)
+    .cfi_rel_offset 28, 52
+    sw     $s7, 48($sp)
+    .cfi_rel_offset 23, 48
+    sw     $s6, 44($sp)
+    .cfi_rel_offset 22, 44
+    sw     $s5, 40($sp)
+    .cfi_rel_offset 21, 40
+    sw     $s4, 36($sp)
+    .cfi_rel_offset 20, 36
+    sw     $s3, 32($sp)
+    .cfi_rel_offset 19, 32
+    sw     $s2, 28($sp)
+    .cfi_rel_offset 18, 28
+    sw     $a3, 12($sp)
+    .cfi_rel_offset 7, 12
+    sw     $a2, 8($sp)
+    .cfi_rel_offset 6, 8
+    sw     $a1, 4($sp)
+    .cfi_rel_offset 5, 4
+    # Begin argument set up.
+    sw      $a0, 0($sp)            # place proxy method at bottom of frame
+    move    $a2, rSELF             # pass Thread::Current
+    jal     artPortableProxyInvokeHandler  # (Method* proxy method, receiver, Thread*, SP)
+    move    $a3, $sp               # pass $sp
+    lw      $ra, 60($sp)           # restore $ra
+    jr      $ra
+    addiu   $sp, $sp, 64           # pop frame
+    .cfi_adjust_cfa_offset -64
+END art_portable_proxy_invoke_handler
+
+    /*
+     * Portable abstract method error stub. $a0 contains method* on entry. SP unused in portable.
+     */
+    .extern artThrowAbstractMethodErrorFromCode
+ENTRY art_portable_abstract_method_error_stub
+    GENERATE_GLOBAL_POINTER
+    la       $t9, artThrowAbstractMethodErrorFromCode
+    jr       $t9            # (Method*, Thread*, SP)
+    move     $a1, $s1       # pass Thread::Current
+END art_portable_abstract_method_error_stub
diff --git a/runtime/arch/mips/quick_entrypoints_init_mips.cc b/runtime/arch/mips/quick_entrypoints_init_mips.cc
deleted file mode 100644
index d494c65..0000000
--- a/runtime/arch/mips/quick_entrypoints_init_mips.cc
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "runtime_support.h"
-
-namespace art {
-
-// Alloc entrypoints.
-extern "C" void* art_quick_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_object_from_code(uint32_t type_idx, void* method);
-extern "C" void* art_quick_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
-extern "C" void* art_quick_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-
-// Cast entrypoints.
-extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass,
-                                            const mirror::Class* ref_class);
-extern "C" void art_quick_can_put_array_element_from_code(void*, void*);
-extern "C" void art_quick_check_cast_from_code(void*, void*);
-
-// DexCache entrypoints.
-extern "C" void* art_quick_initialize_static_storage_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_and_verify_access_from_code(uint32_t, void*);
-extern "C" void* art_quick_resolve_string_from_code(void*, uint32_t);
-
-// Exception entrypoints.
-extern "C" void* GetAndClearException(Thread*);
-
-// Field entrypoints.
-extern "C" int art_quick_set32_instance_from_code(uint32_t, void*, int32_t);
-extern "C" int art_quick_set32_static_from_code(uint32_t, int32_t);
-extern "C" int art_quick_set64_instance_from_code(uint32_t, void*, int64_t);
-extern "C" int art_quick_set64_static_from_code(uint32_t, int64_t);
-extern "C" int art_quick_set_obj_instance_from_code(uint32_t, void*, void*);
-extern "C" int art_quick_set_obj_static_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_instance_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_static_from_code(uint32_t);
-extern "C" int64_t art_quick_get64_instance_from_code(uint32_t, void*);
-extern "C" int64_t art_quick_get64_static_from_code(uint32_t);
-extern "C" void* art_quick_get_obj_instance_from_code(uint32_t, void*);
-extern "C" void* art_quick_get_obj_static_from_code(uint32_t);
-
-// FillArray entrypoint.
-extern "C" void art_quick_handle_fill_data_from_code(void*, void*);
-
-// Lock entrypoints.
-extern "C" void art_quick_lock_object_from_code(void*);
-extern "C" void art_quick_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 "C" int64_t artLmulFromCode(int64_t a, int64_t b);
-extern "C" int64_t artLdivFromCode(int64_t a, int64_t b);
-extern "C" int64_t artLdivmodFromCode(int64_t a, int64_t b);
-
-// Math conversions.
-extern "C" int32_t __fixsfsi(float op1);      // FLOAT_TO_INT
-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 fmodf(float a, float b);      // REM_FLOAT[_2ADDR]
-
-// Double-precision FP arithmetics.
-extern "C" double fmod(double a, double b);     // REM_DOUBLE[_2ADDR]
-
-// Long long arithmetics - REM_LONG[_2ADDR] and DIV_LONG[_2ADDR]
-extern "C" int64_t __divdi3(int64_t, int64_t);
-extern "C" int64_t __moddi3(int64_t, int64_t);
-extern "C" uint64_t art_quick_shl_long(uint64_t, uint32_t);
-extern "C" uint64_t art_quick_shr_long(uint64_t, uint32_t);
-extern "C" uint64_t art_quick_ushr_long(uint64_t, uint32_t);
-
-// Interpreter entrypoints.
-extern "C" void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
-                                                 const DexFile::CodeItem* code_item,
-                                                 ShadowFrame* shadow_frame, JValue* result);
-extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
-                                           const DexFile::CodeItem* code_item,
-                                           ShadowFrame* shadow_frame, JValue* result);
-
-// Intrinsic entrypoints.
-extern "C" int32_t __memcmp16(void*, void*, int32_t);
-extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
-extern "C" int32_t art_quick_string_compareto(void*, void*);
-
-// Invoke entrypoints.
-extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
-                                                       mirror::Object* receiver,
-                                                       mirror::AbstractMethod** sp, Thread* thread);
-extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
-                                                    mirror::Object* receiver,
-                                                    mirror::AbstractMethod** sp, Thread* thread);
-extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
-extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_static_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_super_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
-
-// Thread entrypoints.
-extern void CheckSuspendFromCode(Thread* thread);
-extern "C" void art_quick_test_suspend();
-
-// Throw entrypoints.
-extern "C" void art_quick_deliver_exception_from_code(void*);
-extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit);
-extern "C" void art_quick_throw_div_zero_from_code();
-extern "C" void art_quick_throw_no_such_method_from_code(int32_t method_idx);
-extern "C" void art_quick_throw_null_pointer_exception_from_code();
-extern "C" void art_quick_throw_stack_overflow_from_code(void*);
-
-void InitEntryPoints(QuickEntryPoints* points) {
-  // Alloc
-  points->pAllocArrayFromCode = art_quick_alloc_array_from_code;
-  points->pAllocArrayFromCodeWithAccessCheck = art_quick_alloc_array_from_code_with_access_check;
-  points->pAllocObjectFromCode = art_quick_alloc_object_from_code;
-  points->pAllocObjectFromCodeWithAccessCheck = art_quick_alloc_object_from_code_with_access_check;
-  points->pCheckAndAllocArrayFromCode = art_quick_check_and_alloc_array_from_code;
-  points->pCheckAndAllocArrayFromCodeWithAccessCheck = art_quick_check_and_alloc_array_from_code_with_access_check;
-
-  // Cast
-  points->pInstanceofNonTrivialFromCode = artIsAssignableFromCode;
-  points->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
-  points->pCheckCastFromCode = art_quick_check_cast_from_code;
-
-  // DexCache
-  points->pInitializeStaticStorage = art_quick_initialize_static_storage_from_code;
-  points->pInitializeTypeAndVerifyAccessFromCode = art_quick_initialize_type_and_verify_access_from_code;
-  points->pInitializeTypeFromCode = art_quick_initialize_type_from_code;
-  points->pResolveStringFromCode = art_quick_resolve_string_from_code;
-
-  // Field
-  points->pSet32Instance = art_quick_set32_instance_from_code;
-  points->pSet32Static = art_quick_set32_static_from_code;
-  points->pSet64Instance = art_quick_set64_instance_from_code;
-  points->pSet64Static = art_quick_set64_static_from_code;
-  points->pSetObjInstance = art_quick_set_obj_instance_from_code;
-  points->pSetObjStatic = art_quick_set_obj_static_from_code;
-  points->pGet32Instance = art_quick_get32_instance_from_code;
-  points->pGet64Instance = art_quick_get64_instance_from_code;
-  points->pGetObjInstance = art_quick_get_obj_instance_from_code;
-  points->pGet32Static = art_quick_get32_static_from_code;
-  points->pGet64Static = art_quick_get64_static_from_code;
-  points->pGetObjStatic = art_quick_get_obj_static_from_code;
-
-  // FillArray
-  points->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
-
-  // JNI
-  points->pJniMethodStart = JniMethodStart;
-  points->pJniMethodStartSynchronized = JniMethodStartSynchronized;
-  points->pJniMethodEnd = JniMethodEnd;
-  points->pJniMethodEndSynchronized = JniMethodEndSynchronized;
-  points->pJniMethodEndWithReference = JniMethodEndWithReference;
-  points->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
-
-  // Locks
-  points->pLockObjectFromCode = art_quick_lock_object_from_code;
-  points->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
-
-  // Math
-  points->pCmpgDouble = CmpgDouble;
-  points->pCmpgFloat = CmpgFloat;
-  points->pCmplDouble = CmplDouble;
-  points->pCmplFloat = CmplFloat;
-  points->pFmod = fmod;
-  points->pL2d = __floatdidf;
-  points->pFmodf = fmodf;
-  points->pL2f = __floatdisf;
-  points->pD2iz = __fixdfsi;
-  points->pF2iz = __fixsfsi;
-  points->pIdivmod = NULL;
-  points->pD2l = art_d2l;
-  points->pF2l = art_f2l;
-  points->pLdiv = artLdivFromCode;
-  points->pLdivmod = artLdivmodFromCode;
-  points->pLmul = artLmulFromCode;
-  points->pShlLong = art_quick_shl_long;
-  points->pShrLong = art_quick_shr_long;
-  points->pUshrLong = art_quick_ushr_long;
-
-  // Interpreter
-  points->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
-  points->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
-
-  // Intrinsics
-  points->pIndexOf = art_quick_indexof;
-  points->pMemcmp16 = __memcmp16;
-  points->pStringCompareTo = art_quick_string_compareto;
-  points->pMemcpy = memcpy;
-
-  // Invocation
-  points->pPortableResolutionTrampolineFromCode = artPortableResolutionTrampoline;
-  points->pQuickResolutionTrampolineFromCode = artQuickResolutionTrampoline;
-  points->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
-  points->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
-  points->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
-  points->pInvokeStaticTrampolineWithAccessCheck = art_quick_invoke_static_trampoline_with_access_check;
-  points->pInvokeSuperTrampolineWithAccessCheck = art_quick_invoke_super_trampoline_with_access_check;
-  points->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
-
-  // Thread
-  points->pCheckSuspendFromCode = CheckSuspendFromCode;
-  points->pTestSuspendFromCode = art_quick_test_suspend;
-
-  // Throws
-  points->pDeliverException = art_quick_deliver_exception_from_code;
-  points->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code;
-  points->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code;
-  points->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code;
-  points->pThrowNullPointerFromCode = art_quick_throw_null_pointer_exception_from_code;
-  points->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
-};
-
-}  // namespace art
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 45d583e..d32a2b4 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "asm_support.h"
+#include "asm_support_mips.S"
 
     .set noreorder
     .balign 4
@@ -24,25 +24,6 @@
     /* Deliver an exception pending on a thread */
     .extern artDeliverPendingExceptionFromCode
 
-    /* Cache alignment for function entry */
-.macro ENTRY name
-    .type \name, %function
-    .global \name
-    .balign 16
-\name:
-    .cfi_startproc
-.endm
-
-.macro END name
-    .cfi_endproc
-    .size \name, .-\name
-.endm
-
-    /* Generates $gp for function calls */
-.macro GENERATE_GLOBAL_POINTER
-    .cpload $t9
-.endm
-
     /*
      * Macro that sets up the callee save frame to conform with
      * Runtime::CreateCalleeSaveMethod(kSaveAll)
@@ -481,39 +462,6 @@
     .size art_portable_invoke_stub, .-art_portable_invoke_stub
 
     /*
-     * Entry point of native methods when JNI bug compatibility is enabled.
-     */
-    .extern artWorkAroundAppJniBugs
-ENTRY art_quick_work_around_app_jni_bugs
-    GENERATE_GLOBAL_POINTER
-    # save registers that may contain arguments and LR that will be crushed by a call
-    addiu    $sp, $sp, -32
-    .cfi_adjust_cfa_offset 32
-    sw       $ra, 28($sp)
-    .cfi_rel_offset 31, 28
-    sw       $a3, 24($sp)
-    .cfi_rel_offset 7, 28
-    sw       $a2, 20($sp)
-    .cfi_rel_offset 6, 28
-    sw       $a1, 16($sp)
-    .cfi_rel_offset 5, 28
-    sw       $a0, 12($sp)
-    .cfi_rel_offset 4, 28
-    move     $a0, rSELF       # pass Thread::Current
-    jal      artWorkAroundAppJniBugs  # (Thread*, $sp)
-    move     $a1, $sp         # pass $sp
-    move     $t9, $v0         # save target address
-    lw       $a0, 12($sp)
-    lw       $a1, 16($sp)
-    lw       $a2, 20($sp)
-    lw       $a3, 24($sp)
-    lw       $ra, 28($sp)
-    jr       $t9              # tail call into JNI routine
-    addiu    $sp, $sp, 32
-    .cfi_adjust_cfa_offset -32
-END art_quick_work_around_app_jni_bugs
-
-    /*
      * Entry from managed code that calls artHandleFillArrayDataFromCode and delivers exception on
      * failure.
      */
@@ -912,20 +860,6 @@
     RESTORE_REF_ONLY_CALLEE_SAVE_FRAME_AND_RETURN
 END art_quick_test_suspend
 
-    .extern artPortableProxyInvokeHandler
-ENTRY art_portable_proxy_invoke_handler
-    GENERATE_GLOBAL_POINTER
-    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
-    sw      $a0, 0($sp)            # place proxy method at bottom of frame
-    move    $a2, rSELF             # pass Thread::Current
-    jal     artPortableProxyInvokeHandler  # (Method* proxy method, receiver, Thread*, SP)
-    move    $a3, $sp               # pass $sp
-    lw      $ra, 60($sp)           # restore $ra
-    jr      $ra
-    addiu   $sp, $sp, 64           # pop frame
-    .cfi_adjust_cfa_offset -64
-END art_portable_proxy_invoke_handler
-
     /*
      * 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.
@@ -1044,17 +978,6 @@
 END art_quick_deoptimize
 
     /*
-     * Portable abstract method error stub. $a0 contains method* on entry. SP unused in portable.
-     */
-    .extern artThrowAbstractMethodErrorFromCode
-ENTRY art_portable_abstract_method_error_stub
-    GENERATE_GLOBAL_POINTER
-    la       $t9, artThrowAbstractMethodErrorFromCode
-    jr       $t9            # (Method*, Thread*, SP)
-    move     $a1, $s1       # pass Thread::Current
-END art_portable_abstract_method_error_stub
-
-    /*
      * Quick abstract method error stub. $a0 contains method* on entry.
      */
 ENTRY art_quick_abstract_method_error_stub
@@ -1067,42 +990,6 @@
 END art_quick_abstract_method_error_stub
 
     /*
-     * Jni dlsym lookup stub.
-     */
-    .extern artFindNativeMethod
-ENTRY art_jni_dlsym_lookup_stub
-    GENERATE_GLOBAL_POINTER
-    addiu $sp, $sp, -32          # leave room for $a0, $a1, $a2, $a3, and $ra
-    .cfi_adjust_cfa_offset 32
-    sw     $ra, 16($sp)
-    .cfi_rel_offset 31, 16
-    sw     $a3, 12($sp)
-    .cfi_rel_offset 7, 12
-    sw     $a2, 8($sp)
-    .cfi_rel_offset 6, 8
-    sw     $a1, 4($sp)
-    .cfi_rel_offset 5, 4
-    sw     $a0, 0($sp)
-    .cfi_rel_offset 4, 0
-    jal   artFindNativeMethod   # (Thread*)
-    move  $a0, $s1              # pass Thread::Current()
-    lw    $a0, 0($sp)           # restore registers from stack
-    lw    $a1, 4($sp)
-    lw    $a2, 8($sp)
-    lw    $a3, 12($sp)
-    lw    $ra, 16($sp)
-    beq   $v0, $zero, no_native_code_found
-    addiu $sp, $sp, 32          # restore the stack
-    .cfi_adjust_cfa_offset -32
-    move  $t9, $v0              # put method code result in $t9
-    jr    $t9                   # leaf call to method's code
-    nop
-no_native_code_found:
-    jr    $ra
-    nop
-END art_jni_dlsym_lookup_stub
-
-    /*
      * Long integer shift.  This is different from the generic 32/64-bit
      * binary operations because vAA/vBB are 64-bit but vCC (the shift
      * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
diff --git a/runtime/thread_arm.cc b/runtime/arch/mips/thread_mips.cc
similarity index 93%
rename from runtime/thread_arm.cc
rename to runtime/arch/mips/thread_mips.cc
index 0ef26bf..7364de0 100644
--- a/runtime/thread_arm.cc
+++ b/runtime/arch/mips/thread_mips.cc
@@ -16,8 +16,8 @@
 
 #include "thread.h"
 
-#include "asm_support.h"
-#include "base/macros.h"
+#include "asm_support_mips.h"
+#include "base/logging.h"
 
 namespace art {
 
diff --git a/runtime/arch/x86/asm_support_x86.S b/runtime/arch/x86/asm_support_x86.S
new file mode 100644
index 0000000..7e6dce9
--- /dev/null
+++ b/runtime/arch/x86/asm_support_x86.S
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
+#define ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
+
+#include "asm_support_x86.h"
+
+#if defined(__APPLE__)
+    // Mac OS' as(1) doesn't let you name macro parameters.
+    #define MACRO0(macro_name) .macro macro_name
+    #define MACRO1(macro_name, macro_arg1) .macro macro_name
+    #define MACRO2(macro_name, macro_arg1, macro_args2) .macro macro_name
+    #define MACRO3(macro_name, macro_arg1, macro_args2, macro_args3) .macro macro_name
+    #define END_MACRO .endmacro
+
+    // Mac OS' as(1) uses $0, $1, and so on for macro arguments, and function names
+    // are mangled with an extra underscore prefix. The use of $x for arguments
+    // mean that literals need to be represented with $$x in macros.
+    #define SYMBOL(name) _ ## name
+    #define VAR(name,index) SYMBOL($index)
+    #define REG_VAR(name,index) %$index
+    #define CALL_MACRO(name,index) $index
+    #define LITERAL(value) $value
+    #define MACRO_LITERAL(value) $$value
+#else
+    // Regular gas(1) lets you name macro parameters.
+    #define MACRO0(macro_name) .macro macro_name
+    #define MACRO1(macro_name, macro_arg1) .macro macro_name macro_arg1
+    #define MACRO2(macro_name, macro_arg1, macro_arg2) .macro macro_name macro_arg1, macro_arg2
+    #define MACRO3(macro_name, macro_arg1, macro_arg2, macro_arg3) .macro macro_name macro_arg1, macro_arg2, macro_arg3
+    #define END_MACRO .endm
+
+    // Regular gas(1) uses \argument_name for macro arguments.
+    // We need to turn on alternate macro syntax so we can use & instead or the preprocessor
+    // will screw us by inserting a space between the \ and the name. Even in this mode there's
+    // no special meaning to $, so literals are still just $x. The use of altmacro means % is a
+    // special character meaning care needs to be taken when passing registers as macro arguments.
+    .altmacro
+    #define SYMBOL(name) name
+    #define VAR(name,index) name&
+    #define REG_VAR(name,index) %name
+    #define CALL_MACRO(name,index) name&
+    #define LITERAL(value) $value
+    #define MACRO_LITERAL(value) $value
+#endif
+
+    /* Cache alignment for function entry */
+MACRO0(ALIGN_FUNCTION_ENTRY)
+    .balign 16
+END_MACRO
+
+MACRO1(DEFINE_FUNCTION, c_name)
+    .type VAR(c_name, 0), @function
+    .globl VAR(c_name, 0)
+    ALIGN_FUNCTION_ENTRY
+VAR(c_name, 0):
+    .cfi_startproc
+END_MACRO
+
+MACRO1(END_FUNCTION, c_name)
+    .cfi_endproc
+    .size \c_name, .-\c_name
+END_MACRO
+
+MACRO1(PUSH, reg)
+  pushl REG_VAR(reg, 0)
+  .cfi_adjust_cfa_offset 4
+  .cfi_rel_offset REG_VAR(reg, 0), 0
+END_MACRO
+
+MACRO1(POP, reg)
+  popl REG_VAR(reg,0)
+  .cfi_adjust_cfa_offset -4
+  .cfi_restore REG_VAR(reg,0)
+END_MACRO
+
+#endif  // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_S_
diff --git a/runtime/thread_arm.cc b/runtime/arch/x86/asm_support_x86.h
similarity index 60%
copy from runtime/thread_arm.cc
copy to runtime/arch/x86/asm_support_x86.h
index 0ef26bf..1092910 100644
--- a/runtime/thread_arm.cc
+++ b/runtime/arch/x86/asm_support_x86.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,16 +14,14 @@
  * limitations under the License.
  */
 
-#include "thread.h"
+#ifndef ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_H_
+#define ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_H_
 
 #include "asm_support.h"
-#include "base/macros.h"
 
-namespace art {
+// Offset of field Thread::self_ verified in InitCpu
+#define THREAD_SELF_OFFSET 40
+// Offset of field Thread::exception_ verified in InitCpu
+#define THREAD_EXCEPTION_OFFSET 12
 
-void Thread::InitCpu() {
-  CHECK_EQ(THREAD_FLAGS_OFFSET, OFFSETOF_MEMBER(Thread, state_and_flags_));
-  CHECK_EQ(THREAD_EXCEPTION_OFFSET, OFFSETOF_MEMBER(Thread, exception_));
-}
-
-}  // namespace art
+#endif  // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_H_
diff --git a/runtime/arch/x86/entrypoints_init_x86.cc b/runtime/arch/x86/entrypoints_init_x86.cc
new file mode 100644
index 0000000..d47dfef
--- /dev/null
+++ b/runtime/arch/x86/entrypoints_init_x86.cc
@@ -0,0 +1,224 @@
+/*
+ * 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 "entrypoints/portable/portable_entrypoints.h"
+#include "entrypoints/quick/quick_entrypoints.h"
+#include "entrypoints/entrypoint_utils.h"
+
+namespace art {
+
+// Alloc entrypoints.
+extern "C" void* art_quick_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+extern "C" void* art_quick_alloc_object_from_code(uint32_t type_idx, void* method);
+extern "C" void* art_quick_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
+extern "C" void* art_quick_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
+extern "C" void* art_quick_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
+
+// Cast entrypoints.
+extern "C" uint32_t art_quick_is_assignable_from_code(const mirror::Class* klass,
+                                                const mirror::Class* ref_class);
+extern "C" void art_quick_can_put_array_element_from_code(void*, void*);
+extern "C" void art_quick_check_cast_from_code(void*, void*);
+
+// DexCache entrypoints.
+extern "C" void* art_quick_initialize_static_storage_from_code(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_from_code(uint32_t, void*);
+extern "C" void* art_quick_initialize_type_and_verify_access_from_code(uint32_t, void*);
+extern "C" void* art_quick_resolve_string_from_code(void*, uint32_t);
+
+// Field entrypoints.
+extern "C" int art_quick_set32_instance_from_code(uint32_t, void*, int32_t);
+extern "C" int art_quick_set32_static_from_code(uint32_t, int32_t);
+extern "C" int art_quick_set64_instance_from_code(uint32_t, void*, int64_t);
+extern "C" int art_quick_set64_static_from_code(uint32_t, int64_t);
+extern "C" int art_quick_set_obj_instance_from_code(uint32_t, void*, void*);
+extern "C" int art_quick_set_obj_static_from_code(uint32_t, void*);
+extern "C" int32_t art_quick_get32_instance_from_code(uint32_t, void*);
+extern "C" int32_t art_quick_get32_static_from_code(uint32_t);
+extern "C" int64_t art_quick_get64_instance_from_code(uint32_t, void*);
+extern "C" int64_t art_quick_get64_static_from_code(uint32_t);
+extern "C" void* art_quick_get_obj_instance_from_code(uint32_t, void*);
+extern "C" void* art_quick_get_obj_static_from_code(uint32_t);
+
+// FillArray entrypoint.
+extern "C" void art_quick_handle_fill_data_from_code(void*, void*);
+
+// Lock entrypoints.
+extern "C" void art_quick_lock_object_from_code(void*);
+extern "C" void art_quick_unlock_object_from_code(void*);
+
+// Math entrypoints.
+extern "C" double art_quick_fmod_from_code(double, double);
+extern "C" float art_quick_fmodf_from_code(float, float);
+extern "C" double art_quick_l2d_from_code(int64_t);
+extern "C" float art_quick_l2f_from_code(int64_t);
+extern "C" int64_t art_quick_d2l_from_code(double);
+extern "C" int64_t art_quick_f2l_from_code(float);
+extern "C" int32_t art_quick_idivmod_from_code(int32_t, int32_t);
+extern "C" int64_t art_quick_ldiv_from_code(int64_t, int64_t);
+extern "C" int64_t art_quick_ldivmod_from_code(int64_t, int64_t);
+extern "C" int64_t art_quick_lmul_from_code(int64_t, int64_t);
+extern "C" uint64_t art_quick_lshl_from_code(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_lshr_from_code(uint64_t, uint32_t);
+extern "C" uint64_t art_quick_lushr_from_code(uint64_t, uint32_t);
+
+// Interpreter entrypoints.
+extern "C" void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
+                                                 const DexFile::CodeItem* code_item,
+                                                 ShadowFrame* shadow_frame, JValue* result);
+extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
+                                           const DexFile::CodeItem* code_item,
+                                           ShadowFrame* shadow_frame, JValue* result);
+
+// Intrinsic entrypoints.
+extern "C" int32_t art_quick_memcmp16(void*, void*, int32_t);
+extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
+extern "C" int32_t art_quick_string_compareto(void*, void*);
+extern "C" void* art_quick_memcpy(void*, const void*, size_t);
+
+// Invoke entrypoints.
+extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
+                                                       mirror::Object* receiver,
+                                                       mirror::AbstractMethod** sp, Thread* thread);
+extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
+                                                    mirror::Object* receiver,
+                                                    mirror::AbstractMethod** sp, Thread* thread);
+extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
+extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_static_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_super_trampoline_with_access_check(uint32_t, void*);
+extern "C" void art_quick_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
+
+// Thread entrypoints.
+extern void CheckSuspendFromCode(Thread* thread);
+extern "C" void art_quick_test_suspend();
+
+// Throw entrypoints.
+extern "C" void art_quick_deliver_exception_from_code(void*);
+extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit);
+extern "C" void art_quick_throw_div_zero_from_code();
+extern "C" void art_quick_throw_no_such_method_from_code(int32_t method_idx);
+extern "C" void art_quick_throw_null_pointer_exception_from_code();
+extern "C" void art_quick_throw_stack_overflow_from_code(void*);
+
+void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
+  // Alloc
+  qpoints->pAllocArrayFromCode = art_quick_alloc_array_from_code;
+  qpoints->pAllocArrayFromCodeWithAccessCheck = art_quick_alloc_array_from_code_with_access_check;
+  qpoints->pAllocObjectFromCode = art_quick_alloc_object_from_code;
+  qpoints->pAllocObjectFromCodeWithAccessCheck = art_quick_alloc_object_from_code_with_access_check;
+  qpoints->pCheckAndAllocArrayFromCode = art_quick_check_and_alloc_array_from_code;
+  qpoints->pCheckAndAllocArrayFromCodeWithAccessCheck = art_quick_check_and_alloc_array_from_code_with_access_check;
+
+  // Cast
+  qpoints->pInstanceofNonTrivialFromCode = art_quick_is_assignable_from_code;
+  qpoints->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
+  qpoints->pCheckCastFromCode = art_quick_check_cast_from_code;
+
+  // DexCache
+  qpoints->pInitializeStaticStorage = art_quick_initialize_static_storage_from_code;
+  qpoints->pInitializeTypeAndVerifyAccessFromCode = art_quick_initialize_type_and_verify_access_from_code;
+  qpoints->pInitializeTypeFromCode = art_quick_initialize_type_from_code;
+  qpoints->pResolveStringFromCode = art_quick_resolve_string_from_code;
+
+  // Field
+  qpoints->pSet32Instance = art_quick_set32_instance_from_code;
+  qpoints->pSet32Static = art_quick_set32_static_from_code;
+  qpoints->pSet64Instance = art_quick_set64_instance_from_code;
+  qpoints->pSet64Static = art_quick_set64_static_from_code;
+  qpoints->pSetObjInstance = art_quick_set_obj_instance_from_code;
+  qpoints->pSetObjStatic = art_quick_set_obj_static_from_code;
+  qpoints->pGet32Instance = art_quick_get32_instance_from_code;
+  qpoints->pGet64Instance = art_quick_get64_instance_from_code;
+  qpoints->pGetObjInstance = art_quick_get_obj_instance_from_code;
+  qpoints->pGet32Static = art_quick_get32_static_from_code;
+  qpoints->pGet64Static = art_quick_get64_static_from_code;
+  qpoints->pGetObjStatic = art_quick_get_obj_static_from_code;
+
+  // FillArray
+  qpoints->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
+
+  // JNI
+  qpoints->pJniMethodStart = JniMethodStart;
+  qpoints->pJniMethodStartSynchronized = JniMethodStartSynchronized;
+  qpoints->pJniMethodEnd = JniMethodEnd;
+  qpoints->pJniMethodEndSynchronized = JniMethodEndSynchronized;
+  qpoints->pJniMethodEndWithReference = JniMethodEndWithReference;
+  qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
+
+  // Locks
+  qpoints->pLockObjectFromCode = art_quick_lock_object_from_code;
+  qpoints->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
+
+  // Math
+  // points->pCmpgDouble = NULL;  // Not needed on x86.
+  // points->pCmpgFloat = NULL;  // Not needed on x86.
+  // points->pCmplDouble = NULL;  // Not needed on x86.
+  // points->pCmplFloat = NULL;  // Not needed on x86.
+  qpoints->pFmod = art_quick_fmod_from_code;
+  qpoints->pL2d = art_quick_l2d_from_code;
+  qpoints->pFmodf = art_quick_fmodf_from_code;
+  qpoints->pL2f = art_quick_l2f_from_code;
+  // points->pD2iz = NULL;  // Not needed on x86.
+  // points->pF2iz = NULL;  // Not needed on x86.
+  qpoints->pIdivmod = art_quick_idivmod_from_code;
+  qpoints->pD2l = art_quick_d2l_from_code;
+  qpoints->pF2l = art_quick_f2l_from_code;
+  qpoints->pLdiv = art_quick_ldiv_from_code;
+  qpoints->pLdivmod = art_quick_ldivmod_from_code;
+  qpoints->pLmul = art_quick_lmul_from_code;
+  qpoints->pShlLong = art_quick_lshl_from_code;
+  qpoints->pShrLong = art_quick_lshr_from_code;
+  qpoints->pUshrLong = art_quick_lushr_from_code;
+
+  // Interpreter
+  qpoints->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
+  qpoints->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
+
+  // Intrinsics
+  qpoints->pIndexOf = art_quick_indexof;
+  qpoints->pMemcmp16 = art_quick_memcmp16;
+  qpoints->pStringCompareTo = art_quick_string_compareto;
+  qpoints->pMemcpy = art_quick_memcpy;
+
+  // Invocation
+  qpoints->pQuickResolutionTrampolineFromCode = artQuickResolutionTrampoline;
+  qpoints->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
+  qpoints->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
+  qpoints->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
+  qpoints->pInvokeStaticTrampolineWithAccessCheck = art_quick_invoke_static_trampoline_with_access_check;
+  qpoints->pInvokeSuperTrampolineWithAccessCheck = art_quick_invoke_super_trampoline_with_access_check;
+  qpoints->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
+
+  // Thread
+  qpoints->pCheckSuspendFromCode = CheckSuspendFromCode;
+  qpoints->pTestSuspendFromCode = art_quick_test_suspend;
+
+  // Throws
+  qpoints->pDeliverException = art_quick_deliver_exception_from_code;
+  qpoints->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code;
+  qpoints->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code;
+  qpoints->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code;
+  qpoints->pThrowNullPointerFromCode = art_quick_throw_null_pointer_exception_from_code;
+  qpoints->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
+
+  // Portable
+  ppoints->pPortableResolutionTrampolineFromCode = artPortableResolutionTrampoline;
+};
+
+}  // namespace art
diff --git a/runtime/arch/x86/jni_entrypoints_x86.S b/runtime/arch/x86/jni_entrypoints_x86.S
new file mode 100644
index 0000000..e9c88fe
--- /dev/null
+++ b/runtime/arch/x86/jni_entrypoints_x86.S
@@ -0,0 +1,35 @@
+/*
+ * 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 "asm_support_x86.S"
+
+    /*
+     * Portable resolution trampoline.
+     */
+DEFINE_FUNCTION art_jni_dlsym_lookup_stub
+    subl LITERAL(8), %esp         // align stack
+    .cfi_adjust_cfa_offset 8
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    .cfi_adjust_cfa_offset 4
+    call SYMBOL(artFindNativeMethod)  // (Thread*)
+    addl LITERAL(12), %esp        // restore the stack
+    .cfi_adjust_cfa_offset -12
+    cmpl LITERAL(0), %eax         // check if returned method code is null
+    je no_native_code_found       // if null, jump to return to handle
+    jmp *%eax                     // otherwise, tail call to intended method
+no_native_code_found:
+    ret
+END_FUNCTION art_jni_dlsym_lookup_stub
diff --git a/runtime/arch/x86/portable_entrypoints_x86.S b/runtime/arch/x86/portable_entrypoints_x86.S
new file mode 100644
index 0000000..a0fca6c
--- /dev/null
+++ b/runtime/arch/x86/portable_entrypoints_x86.S
@@ -0,0 +1,109 @@
+/*
+ * 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 "asm_support_x86.S"
+
+    /*
+     * Portable invocation stub.
+     * On entry:
+     *   [sp] = return address
+     *   [sp + 4] = method pointer
+     *   [sp + 8] = argument array or NULL for no argument methods
+     *   [sp + 12] = size of argument array in bytes
+     *   [sp + 16] = (managed) thread pointer
+     *   [sp + 20] = JValue* result
+     *   [sp + 24] = result type char
+     */
+DEFINE_FUNCTION art_portable_invoke_stub
+    PUSH ebp                      // save ebp
+    PUSH ebx                      // save ebx
+    mov %esp, %ebp                // copy value of stack pointer into base pointer
+    .cfi_def_cfa_register ebp
+    mov 20(%ebp), %ebx            // get arg array size
+    addl LITERAL(28), %ebx        // reserve space for return addr, method*, ebx, and ebp in frame
+    andl LITERAL(0xFFFFFFF0), %ebx    // align frame size to 16 bytes
+    subl LITERAL(12), %ebx        // remove space for return address, ebx, and ebp
+    subl %ebx, %esp               // reserve stack space for argument array
+    lea  4(%esp), %eax            // use stack pointer + method ptr as dest for memcpy
+    pushl 20(%ebp)                // push size of region to memcpy
+    pushl 16(%ebp)                // push arg array as source of memcpy
+    pushl %eax                    // push stack pointer as destination of memcpy
+    call SYMBOL(memcpy)           // (void*, const void*, size_t)
+    addl LITERAL(12), %esp        // pop arguments to memcpy
+    mov 12(%ebp), %eax            // move method pointer into eax
+    mov %eax, (%esp)              // push method pointer onto stack
+    call *METHOD_CODE_OFFSET(%eax) // call the method
+    mov %ebp, %esp                // restore stack pointer
+    POP ebx                       // pop ebx
+    POP ebp                       // pop ebp
+    mov 20(%esp), %ecx            // get result pointer
+    cmpl LITERAL(68), 24(%esp)    // test if result type char == 'D'
+    je return_double_portable
+    cmpl LITERAL(70), 24(%esp)    // test if result type char == 'F'
+    je return_float_portable
+    mov %eax, (%ecx)              // store the result
+    mov %edx, 4(%ecx)             // store the other half of the result
+    ret
+return_double_portable:
+    fstpl (%ecx)                  // store the floating point result as double
+    ret
+return_float_portable:
+    fstps (%ecx)                  // store the floating point result as float
+    ret
+END_FUNCTION art_portable_invoke_stub
+
+DEFINE_FUNCTION art_portable_proxy_invoke_handler
+    // Fake callee save ref and args frame set up, note portable doesn't use callee save frames.
+    // TODO: just save the registers that are needed in artPortableProxyInvokeHandler.
+    PUSH edi  // Save callee saves
+    PUSH esi
+    PUSH ebp
+    PUSH ebx  // Save args
+    PUSH edx
+    PUSH ecx
+    PUSH eax   // Align stack, eax will be clobbered by Method*
+    // Begin argument set up.
+    PUSH esp                      // pass SP
+    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
+    .cfi_adjust_cfa_offset 4
+    PUSH ecx                      // pass receiver
+    PUSH eax                      // pass proxy method
+    call SYMBOL(artPortableProxyInvokeHandler) // (proxy method, receiver, Thread*, SP)
+    movd %eax, %xmm0              // place return value also into floating point return value
+    movd %edx, %xmm1
+    punpckldq %xmm1, %xmm0
+    addl LITERAL(44), %esp        // pop arguments
+    .cfi_adjust_cfa_offset -44
+    ret
+END_FUNCTION art_portable_proxy_invoke_handler
+
+    /*
+     * Portable abstract method error stub. method* is at %esp + 4 on entry.
+     */
+DEFINE_FUNCTION art_portable_abstract_method_error_stub
+    PUSH ebp
+    movl %esp, %ebp               // Remember SP.
+    .cfi_def_cfa_register ebp
+    subl LITERAL(12), %esp        // Align stack.
+    PUSH esp                      // Pass sp (not used).
+    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
+    pushl 8(%ebp)                 // Pass Method*.
+    call SYMBOL(artThrowAbstractMethodErrorFromCode)  // (Method*, Thread*, SP)
+    leave                         // Restore the stack and %ebp.
+    .cfi_def_cfa esp, 4
+    .cfi_restore ebp
+    ret                           // Return to caller to handle pending exception.
+END_FUNCTION art_portable_abstract_method_error_stub
diff --git a/runtime/arch/x86/quick_entrypoints_init_x86.cc b/runtime/arch/x86/quick_entrypoints_init_x86.cc
deleted file mode 100644
index cced916..0000000
--- a/runtime/arch/x86/quick_entrypoints_init_x86.cc
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "entrypoints/quick/quick_entrypoints.h"
-#include "runtime_support.h"
-
-namespace art {
-
-// Alloc entrypoints.
-extern "C" void* art_quick_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-extern "C" void* art_quick_alloc_object_from_code(uint32_t type_idx, void* method);
-extern "C" void* art_quick_alloc_object_from_code_with_access_check(uint32_t type_idx, void* method);
-extern "C" void* art_quick_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
-extern "C" void* art_quick_check_and_alloc_array_from_code_with_access_check(uint32_t, void*, int32_t);
-
-// Cast entrypoints.
-extern "C" uint32_t art_quick_is_assignable_from_code(const mirror::Class* klass,
-                                                const mirror::Class* ref_class);
-extern "C" void art_quick_can_put_array_element_from_code(void*, void*);
-extern "C" void art_quick_check_cast_from_code(void*, void*);
-
-// DexCache entrypoints.
-extern "C" void* art_quick_initialize_static_storage_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_from_code(uint32_t, void*);
-extern "C" void* art_quick_initialize_type_and_verify_access_from_code(uint32_t, void*);
-extern "C" void* art_quick_resolve_string_from_code(void*, uint32_t);
-
-// Field entrypoints.
-extern "C" int art_quick_set32_instance_from_code(uint32_t, void*, int32_t);
-extern "C" int art_quick_set32_static_from_code(uint32_t, int32_t);
-extern "C" int art_quick_set64_instance_from_code(uint32_t, void*, int64_t);
-extern "C" int art_quick_set64_static_from_code(uint32_t, int64_t);
-extern "C" int art_quick_set_obj_instance_from_code(uint32_t, void*, void*);
-extern "C" int art_quick_set_obj_static_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_instance_from_code(uint32_t, void*);
-extern "C" int32_t art_quick_get32_static_from_code(uint32_t);
-extern "C" int64_t art_quick_get64_instance_from_code(uint32_t, void*);
-extern "C" int64_t art_quick_get64_static_from_code(uint32_t);
-extern "C" void* art_quick_get_obj_instance_from_code(uint32_t, void*);
-extern "C" void* art_quick_get_obj_static_from_code(uint32_t);
-
-// FillArray entrypoint.
-extern "C" void art_quick_handle_fill_data_from_code(void*, void*);
-
-// Lock entrypoints.
-extern "C" void art_quick_lock_object_from_code(void*);
-extern "C" void art_quick_unlock_object_from_code(void*);
-
-// Math entrypoints.
-extern "C" double art_quick_fmod_from_code(double, double);
-extern "C" float art_quick_fmodf_from_code(float, float);
-extern "C" double art_quick_l2d_from_code(int64_t);
-extern "C" float art_quick_l2f_from_code(int64_t);
-extern "C" int64_t art_quick_d2l_from_code(double);
-extern "C" int64_t art_quick_f2l_from_code(float);
-extern "C" int32_t art_quick_idivmod_from_code(int32_t, int32_t);
-extern "C" int64_t art_quick_ldiv_from_code(int64_t, int64_t);
-extern "C" int64_t art_quick_ldivmod_from_code(int64_t, int64_t);
-extern "C" int64_t art_quick_lmul_from_code(int64_t, int64_t);
-extern "C" uint64_t art_quick_lshl_from_code(uint64_t, uint32_t);
-extern "C" uint64_t art_quick_lshr_from_code(uint64_t, uint32_t);
-extern "C" uint64_t art_quick_lushr_from_code(uint64_t, uint32_t);
-
-// Interpreter entrypoints.
-extern "C" void artInterpreterToInterpreterEntry(Thread* self, MethodHelper& mh,
-                                                 const DexFile::CodeItem* code_item,
-                                                 ShadowFrame* shadow_frame, JValue* result);
-extern "C" void artInterpreterToQuickEntry(Thread* self, MethodHelper& mh,
-                                           const DexFile::CodeItem* code_item,
-                                           ShadowFrame* shadow_frame, JValue* result);
-
-// Intrinsic entrypoints.
-extern "C" int32_t art_quick_memcmp16(void*, void*, int32_t);
-extern "C" int32_t art_quick_indexof(void*, uint32_t, uint32_t, uint32_t);
-extern "C" int32_t art_quick_string_compareto(void*, void*);
-extern "C" void* art_quick_memcpy(void*, const void*, size_t);
-
-// Invoke entrypoints.
-extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
-                                                       mirror::Object* receiver,
-                                                       mirror::AbstractMethod** sp, Thread* thread);
-extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
-                                                    mirror::Object* receiver,
-                                                    mirror::AbstractMethod** sp, Thread* thread);
-extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
-extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_static_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_super_trampoline_with_access_check(uint32_t, void*);
-extern "C" void art_quick_invoke_virtual_trampoline_with_access_check(uint32_t, void*);
-
-// Thread entrypoints.
-extern void CheckSuspendFromCode(Thread* thread);
-extern "C" void art_quick_test_suspend();
-
-// Throw entrypoints.
-extern "C" void art_quick_deliver_exception_from_code(void*);
-extern "C" void art_quick_throw_array_bounds_from_code(int32_t index, int32_t limit);
-extern "C" void art_quick_throw_div_zero_from_code();
-extern "C" void art_quick_throw_no_such_method_from_code(int32_t method_idx);
-extern "C" void art_quick_throw_null_pointer_exception_from_code();
-extern "C" void art_quick_throw_stack_overflow_from_code(void*);
-
-void InitEntryPoints(QuickEntryPoints* points) {
-  // Alloc
-  points->pAllocArrayFromCode = art_quick_alloc_array_from_code;
-  points->pAllocArrayFromCodeWithAccessCheck = art_quick_alloc_array_from_code_with_access_check;
-  points->pAllocObjectFromCode = art_quick_alloc_object_from_code;
-  points->pAllocObjectFromCodeWithAccessCheck = art_quick_alloc_object_from_code_with_access_check;
-  points->pCheckAndAllocArrayFromCode = art_quick_check_and_alloc_array_from_code;
-  points->pCheckAndAllocArrayFromCodeWithAccessCheck = art_quick_check_and_alloc_array_from_code_with_access_check;
-
-  // Cast
-  points->pInstanceofNonTrivialFromCode = art_quick_is_assignable_from_code;
-  points->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
-  points->pCheckCastFromCode = art_quick_check_cast_from_code;
-
-  // DexCache
-  points->pInitializeStaticStorage = art_quick_initialize_static_storage_from_code;
-  points->pInitializeTypeAndVerifyAccessFromCode = art_quick_initialize_type_and_verify_access_from_code;
-  points->pInitializeTypeFromCode = art_quick_initialize_type_from_code;
-  points->pResolveStringFromCode = art_quick_resolve_string_from_code;
-
-  // Field
-  points->pSet32Instance = art_quick_set32_instance_from_code;
-  points->pSet32Static = art_quick_set32_static_from_code;
-  points->pSet64Instance = art_quick_set64_instance_from_code;
-  points->pSet64Static = art_quick_set64_static_from_code;
-  points->pSetObjInstance = art_quick_set_obj_instance_from_code;
-  points->pSetObjStatic = art_quick_set_obj_static_from_code;
-  points->pGet32Instance = art_quick_get32_instance_from_code;
-  points->pGet64Instance = art_quick_get64_instance_from_code;
-  points->pGetObjInstance = art_quick_get_obj_instance_from_code;
-  points->pGet32Static = art_quick_get32_static_from_code;
-  points->pGet64Static = art_quick_get64_static_from_code;
-  points->pGetObjStatic = art_quick_get_obj_static_from_code;
-
-  // FillArray
-  points->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
-
-  // JNI
-  points->pJniMethodStart = JniMethodStart;
-  points->pJniMethodStartSynchronized = JniMethodStartSynchronized;
-  points->pJniMethodEnd = JniMethodEnd;
-  points->pJniMethodEndSynchronized = JniMethodEndSynchronized;
-  points->pJniMethodEndWithReference = JniMethodEndWithReference;
-  points->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
-
-  // Locks
-  points->pLockObjectFromCode = art_quick_lock_object_from_code;
-  points->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
-
-  // Math
-  // points->pCmpgDouble = NULL;  // Not needed on x86.
-  // points->pCmpgFloat = NULL;  // Not needed on x86.
-  // points->pCmplDouble = NULL;  // Not needed on x86.
-  // points->pCmplFloat = NULL;  // Not needed on x86.
-  points->pFmod = art_quick_fmod_from_code;
-  points->pL2d = art_quick_l2d_from_code;
-  points->pFmodf = art_quick_fmodf_from_code;
-  points->pL2f = art_quick_l2f_from_code;
-  // points->pD2iz = NULL;  // Not needed on x86.
-  // points->pF2iz = NULL;  // Not needed on x86.
-  points->pIdivmod = art_quick_idivmod_from_code;
-  points->pD2l = art_quick_d2l_from_code;
-  points->pF2l = art_quick_f2l_from_code;
-  points->pLdiv = art_quick_ldiv_from_code;
-  points->pLdivmod = art_quick_ldivmod_from_code;
-  points->pLmul = art_quick_lmul_from_code;
-  points->pShlLong = art_quick_lshl_from_code;
-  points->pShrLong = art_quick_lshr_from_code;
-  points->pUshrLong = art_quick_lushr_from_code;
-
-  // Interpreter
-  points->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
-  points->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
-
-  // Intrinsics
-  points->pIndexOf = art_quick_indexof;
-  points->pMemcmp16 = art_quick_memcmp16;
-  points->pStringCompareTo = art_quick_string_compareto;
-  points->pMemcpy = art_quick_memcpy;
-
-  // Invocation
-  points->pPortableResolutionTrampolineFromCode = artPortableResolutionTrampoline;
-  points->pQuickResolutionTrampolineFromCode = artQuickResolutionTrampoline;
-  points->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
-  points->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
-  points->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
-  points->pInvokeStaticTrampolineWithAccessCheck = art_quick_invoke_static_trampoline_with_access_check;
-  points->pInvokeSuperTrampolineWithAccessCheck = art_quick_invoke_super_trampoline_with_access_check;
-  points->pInvokeVirtualTrampolineWithAccessCheck = art_quick_invoke_virtual_trampoline_with_access_check;
-
-  // Thread
-  points->pCheckSuspendFromCode = CheckSuspendFromCode;
-  points->pTestSuspendFromCode = art_quick_test_suspend;
-
-  // Throws
-  points->pDeliverException = art_quick_deliver_exception_from_code;
-  points->pThrowArrayBoundsFromCode = art_quick_throw_array_bounds_from_code;
-  points->pThrowDivZeroFromCode = art_quick_throw_div_zero_from_code;
-  points->pThrowNoSuchMethodFromCode = art_quick_throw_no_such_method_from_code;
-  points->pThrowNullPointerFromCode = art_quick_throw_null_pointer_exception_from_code;
-  points->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
-};
-
-}  // namespace art
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index ee6db0c..89ea71a 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -14,76 +14,7 @@
  * limitations under the License.
  */
 
-#include "asm_support.h"
-
-#if defined(__APPLE__)
-    // Mac OS' as(1) doesn't let you name macro parameters.
-    #define MACRO0(macro_name) .macro macro_name
-    #define MACRO1(macro_name, macro_arg1) .macro macro_name
-    #define MACRO2(macro_name, macro_arg1, macro_args2) .macro macro_name
-    #define MACRO3(macro_name, macro_arg1, macro_args2, macro_args3) .macro macro_name
-    #define END_MACRO .endmacro
-
-    // Mac OS' as(1) uses $0, $1, and so on for macro arguments, and function names
-    // are mangled with an extra underscore prefix. The use of $x for arguments
-    // mean that literals need to be represented with $$x in macros.
-    #define SYMBOL(name) _ ## name
-    #define VAR(name,index) SYMBOL($index)
-    #define REG_VAR(name,index) %$index
-    #define CALL_MACRO(name,index) $index
-    #define LITERAL(value) $value
-    #define MACRO_LITERAL(value) $$value
-#else
-    // Regular gas(1) lets you name macro parameters.
-    #define MACRO0(macro_name) .macro macro_name
-    #define MACRO1(macro_name, macro_arg1) .macro macro_name macro_arg1
-    #define MACRO2(macro_name, macro_arg1, macro_arg2) .macro macro_name macro_arg1, macro_arg2
-    #define MACRO3(macro_name, macro_arg1, macro_arg2, macro_arg3) .macro macro_name macro_arg1, macro_arg2, macro_arg3
-    #define END_MACRO .endm
-
-    // Regular gas(1) uses \argument_name for macro arguments.
-    // We need to turn on alternate macro syntax so we can use & instead or the preprocessor
-    // will screw us by inserting a space between the \ and the name. Even in this mode there's
-    // no special meaning to $, so literals are still just $x. The use of altmacro means % is a
-    // special character meaning care needs to be taken when passing registers as macro arguments.
-    .altmacro
-    #define SYMBOL(name) name
-    #define VAR(name,index) name&
-    #define REG_VAR(name,index) %name
-    #define CALL_MACRO(name,index) name&
-    #define LITERAL(value) $value
-    #define MACRO_LITERAL(value) $value
-#endif
-
-    /* Cache alignment for function entry */
-MACRO0(ALIGN_FUNCTION_ENTRY)
-    .balign 16
-END_MACRO
-
-MACRO1(DEFINE_FUNCTION, c_name)
-    .type VAR(c_name, 0), @function
-    .globl VAR(c_name, 0)
-    ALIGN_FUNCTION_ENTRY
-VAR(c_name, 0):
-    .cfi_startproc
-END_MACRO
-
-MACRO1(END_FUNCTION, c_name)
-    .cfi_endproc
-    .size \c_name, .-\c_name
-END_MACRO
-
-MACRO1(PUSH, reg)
-  pushl REG_VAR(reg, 0)
-  .cfi_adjust_cfa_offset 4
-  .cfi_rel_offset REG_VAR(reg, 0), 0
-END_MACRO
-
-MACRO1(POP, reg)
-  popl REG_VAR(reg,0)
-  .cfi_adjust_cfa_offset -4
-  .cfi_restore REG_VAR(reg,0)
-END_MACRO
+#include "asm_support_x86.S"
 
     /*
      * Macro that sets up the callee save frame to conform with
@@ -302,55 +233,6 @@
 INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
 
     /*
-     * Portable invocation stub.
-     * On entry:
-     *   [sp] = return address
-     *   [sp + 4] = method pointer
-     *   [sp + 8] = argument array or NULL for no argument methods
-     *   [sp + 12] = size of argument array in bytes
-     *   [sp + 16] = (managed) thread pointer
-     *   [sp + 20] = JValue* result
-     *   [sp + 24] = result type char
-     */
-DEFINE_FUNCTION art_portable_invoke_stub
-    PUSH ebp                      // save ebp
-    PUSH ebx                      // save ebx
-    mov %esp, %ebp                // copy value of stack pointer into base pointer
-    .cfi_def_cfa_register ebp
-    mov 20(%ebp), %ebx            // get arg array size
-    addl LITERAL(28), %ebx        // reserve space for return addr, method*, ebx, and ebp in frame
-    andl LITERAL(0xFFFFFFF0), %ebx    // align frame size to 16 bytes
-    subl LITERAL(12), %ebx        // remove space for return address, ebx, and ebp
-    subl %ebx, %esp               // reserve stack space for argument array
-    lea  4(%esp), %eax            // use stack pointer + method ptr as dest for memcpy
-    pushl 20(%ebp)                // push size of region to memcpy
-    pushl 16(%ebp)                // push arg array as source of memcpy
-    pushl %eax                    // push stack pointer as destination of memcpy
-    call SYMBOL(memcpy)           // (void*, const void*, size_t)
-    addl LITERAL(12), %esp        // pop arguments to memcpy
-    mov 12(%ebp), %eax            // move method pointer into eax
-    mov %eax, (%esp)              // push method pointer onto stack
-    call *METHOD_CODE_OFFSET(%eax) // call the method
-    mov %ebp, %esp                // restore stack pointer
-    POP ebx                       // pop ebx
-    POP ebp                       // pop ebp
-    mov 20(%esp), %ecx            // get result pointer
-    cmpl LITERAL(68), 24(%esp)    // test if result type char == 'D'
-    je return_double_portable
-    cmpl LITERAL(70), 24(%esp)    // test if result type char == 'F'
-    je return_float_portable
-    mov %eax, (%ecx)              // store the result
-    mov %edx, 4(%ecx)             // store the other half of the result
-    ret
-return_double_portable:
-    fstpl (%ecx)                  // store the floating point result as double
-    ret
-return_float_portable:
-    fstps (%ecx)                  // store the floating point result as float
-    ret
-END_FUNCTION art_portable_invoke_stub
-
-    /*
      * Quick invocation stub.
      * On entry:
      *   [sp] = return address
@@ -920,22 +802,6 @@
     RETURN_OR_DELIVER_PENDING_EXCEPTION    // return or deliver exception
 END_FUNCTION art_quick_get_obj_static_from_code
 
-DEFINE_FUNCTION art_portable_proxy_invoke_handler
-    SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME   // save frame and Method*
-    PUSH esp                      // pass SP
-    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
-    .cfi_adjust_cfa_offset 4
-    PUSH ecx                      // pass receiver
-    PUSH eax                      // pass proxy method
-    call SYMBOL(artPortableProxyInvokeHandler) // (proxy method, receiver, Thread*, SP)
-    movd %eax, %xmm0              // place return value also into floating point return value
-    movd %edx, %xmm1
-    punpckldq %xmm1, %xmm0
-    addl LITERAL(44), %esp        // pop arguments
-    .cfi_adjust_cfa_offset -44
-    ret
-END_FUNCTION art_portable_proxy_invoke_handler
-
 DEFINE_FUNCTION art_quick_proxy_invoke_handler
     SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME   // save frame and Method*
     PUSH esp                      // pass SP
@@ -1054,24 +920,6 @@
 END_FUNCTION art_quick_deoptimize
 
     /*
-     * Portable abstract method error stub. method* is at %esp + 4 on entry.
-     */
-DEFINE_FUNCTION art_portable_abstract_method_error_stub
-    PUSH ebp
-    movl %esp, %ebp               // Remember SP.
-    .cfi_def_cfa_register ebp
-    subl LITERAL(12), %esp        // Align stack.
-    PUSH esp                      // Pass sp (not used).
-    pushl %fs:THREAD_SELF_OFFSET  // Pass Thread::Current().
-    pushl 8(%ebp)                 // Pass Method*.
-    call SYMBOL(artThrowAbstractMethodErrorFromCode)  // (Method*, Thread*, SP)
-    leave                         // Restore the stack and %ebp.
-    .cfi_def_cfa esp, 4
-    .cfi_restore ebp
-    ret                           // Return to caller to handle pending exception.
-END_FUNCTION art_portable_abstract_method_error_stub
-
-    /*
      * Quick abstract method error stub. %eax contains method* on entry.
      */
 DEFINE_FUNCTION art_quick_abstract_method_error_stub
@@ -1087,24 +935,6 @@
 END_FUNCTION art_quick_abstract_method_error_stub
 
     /*
-     * Portable resolution trampoline.
-     */
-DEFINE_FUNCTION art_jni_dlsym_lookup_stub
-    subl LITERAL(8), %esp         // align stack
-    .cfi_adjust_cfa_offset 8
-    pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
-    .cfi_adjust_cfa_offset 4
-    call SYMBOL(artFindNativeMethod)  // (Thread*)
-    addl LITERAL(12), %esp        // restore the stack
-    .cfi_adjust_cfa_offset -12
-    cmpl LITERAL(0), %eax         // check if returned method code is null
-    je no_native_code_found       // if null, jump to return to handle
-    jmp *%eax                     // otherwise, tail call to intended method
-no_native_code_found:
-    ret
-END_FUNCTION art_jni_dlsym_lookup_stub
-
-    /*
      * String's indexOf.
      *
      * On entry:
diff --git a/runtime/thread_x86.cc b/runtime/arch/x86/thread_x86.cc
similarity index 98%
rename from runtime/thread_x86.cc
rename to runtime/arch/x86/thread_x86.cc
index c398b28..dd3e7dd 100644
--- a/runtime/thread_x86.cc
+++ b/runtime/arch/x86/thread_x86.cc
@@ -19,7 +19,7 @@
 #include <sys/syscall.h>
 #include <sys/types.h>
 
-#include "asm_support.h"
+#include "asm_support_x86.h"
 #include "base/macros.h"
 #include "thread.h"
 #include "thread_list.h"
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 7b20c7a..aca93a5 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -30,29 +30,4 @@
 // Offset of field Method::entry_point_from_compiled_code_
 #define METHOD_CODE_OFFSET 40
 
-#if defined(__arm__)
-// Register holding suspend check count down.
-#define rSUSPEND r4
-// Register holding Thread::Current().
-#define rSELF r9
-// Offset of field Thread::suspend_count_ verified in InitCpu
-#define THREAD_FLAGS_OFFSET 0
-// Offset of field Thread::exception_ verified in InitCpu
-#define THREAD_EXCEPTION_OFFSET 12
-#elif defined(__mips__)
-// Register holding suspend check count down.
-#define rSUSPEND $s0
-// Register holding Thread::Current().
-#define rSELF $s1
-// Offset of field Thread::suspend_count_ verified in InitCpu
-#define THREAD_FLAGS_OFFSET 0
-// Offset of field Thread::exception_ verified in InitCpu
-#define THREAD_EXCEPTION_OFFSET 12
-#elif defined(__i386__)
-// Offset of field Thread::self_ verified in InitCpu
-#define THREAD_SELF_OFFSET 40
-// Offset of field Thread::exception_ verified in InitCpu
-#define THREAD_EXCEPTION_OFFSET 12
-#endif
-
 #endif  // ART_RUNTIME_ASM_SUPPORT_H_
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 72e0f48..84f186d 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -58,10 +58,7 @@
 #include "object_utils.h"
 #include "os.h"
 #include "runtime.h"
-#include "runtime_support.h"
-#if defined(ART_USE_PORTABLE_COMPILER)
-#include "runtime_support_llvm.h"
-#endif
+#include "entrypoints/entrypoint_utils.h"
 #include "ScopedLocalRef.h"
 #include "scoped_thread_state_change.h"
 #include "sirt_ref.h"
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 75886cf..4659fd1 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -22,6 +22,7 @@
 #include "class_linker-inl.h"
 #include "common_test.h"
 #include "dex_file.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "gc/heap.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache.h"
@@ -32,7 +33,6 @@
 #include "mirror/object_array-inl.h"
 #include "mirror/proxy.h"
 #include "mirror/stack_trace_element.h"
-#include "runtime_support.h"
 #include "sirt_ref.h"
 
 using ::art::mirror::AbstractMethod;
diff --git a/runtime/common_test.h b/runtime/common_test.h
index 2c23340..7ee6fe2 100644
--- a/runtime/common_test.h
+++ b/runtime/common_test.h
@@ -31,6 +31,7 @@
 #include "class_linker.h"
 #include "compiler/driver/compiler_driver.h"
 #include "dex_file-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "gc/heap.h"
 #include "gtest/gtest.h"
 #include "instruction_set.h"
@@ -39,7 +40,6 @@
 #include "object_utils.h"
 #include "os.h"
 #include "runtime.h"
-#include "runtime_support.h"
 #include "scoped_thread_state_change.h"
 #include "ScopedLocalRef.h"
 #include "thread.h"
diff --git a/runtime/runtime_support.cc b/runtime/entrypoints/entrypoint_utils.cc
similarity index 89%
rename from runtime/runtime_support.cc
rename to runtime/entrypoints/entrypoint_utils.cc
index d28aad1..c297841 100644
--- a/runtime/runtime_support.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "runtime_support.h"
+#include "entrypoints/entrypoint_utils.h"
 
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
@@ -30,74 +30,6 @@
 #include "ScopedLocalRef.h"
 #include "well_known_classes.h"
 
-double art_l2d(int64_t l) {
-  return static_cast<double>(l);
-}
-
-float art_l2f(int64_t l) {
-  return static_cast<float>(l);
-}
-
-/*
- * Float/double conversion requires clamping to min and max of integer form.  If
- * target doesn't support this normally, use these.
- */
-int64_t art_d2l(double d) {
-  static const double kMaxLong = static_cast<double>(static_cast<int64_t>(0x7fffffffffffffffULL));
-  static const double kMinLong = static_cast<double>(static_cast<int64_t>(0x8000000000000000ULL));
-  if (d >= kMaxLong) {
-    return static_cast<int64_t>(0x7fffffffffffffffULL);
-  } else if (d <= kMinLong) {
-    return static_cast<int64_t>(0x8000000000000000ULL);
-  } else if (d != d)  {  // NaN case
-    return 0;
-  } else {
-    return static_cast<int64_t>(d);
-  }
-}
-
-int64_t art_f2l(float f) {
-  static const float kMaxLong = static_cast<float>(static_cast<int64_t>(0x7fffffffffffffffULL));
-  static const float kMinLong = static_cast<float>(static_cast<int64_t>(0x8000000000000000ULL));
-  if (f >= kMaxLong) {
-    return static_cast<int64_t>(0x7fffffffffffffffULL);
-  } else if (f <= kMinLong) {
-    return static_cast<int64_t>(0x8000000000000000ULL);
-  } else if (f != f) {  // NaN case
-    return 0;
-  } else {
-    return static_cast<int64_t>(f);
-  }
-}
-
-int32_t art_d2i(double d) {
-  static const double kMaxInt = static_cast<double>(static_cast<int32_t>(0x7fffffffUL));
-  static const double kMinInt = static_cast<double>(static_cast<int32_t>(0x80000000UL));
-  if (d >= kMaxInt) {
-    return static_cast<int32_t>(0x7fffffffUL);
-  } else if (d <= kMinInt) {
-    return static_cast<int32_t>(0x80000000UL);
-  } else if (d != d)  {  // NaN case
-    return 0;
-  } else {
-    return static_cast<int32_t>(d);
-  }
-}
-
-int32_t art_f2i(float f) {
-  static const float kMaxInt = static_cast<float>(static_cast<int32_t>(0x7fffffffUL));
-  static const float kMinInt = static_cast<float>(static_cast<int32_t>(0x80000000UL));
-  if (f >= kMaxInt) {
-    return static_cast<int32_t>(0x7fffffffUL);
-  } else if (f <= kMinInt) {
-    return static_cast<int32_t>(0x80000000UL);
-  } else if (f != f) {  // NaN case
-    return 0;
-  } else {
-    return static_cast<int32_t>(f);
-  }
-}
-
 namespace art {
 
 // Helper function to allocate array for FILLED_NEW_ARRAY.
diff --git a/runtime/runtime_support.h b/runtime/entrypoints/entrypoint_utils.h
similarity index 97%
rename from runtime/runtime_support.h
rename to runtime/entrypoints/entrypoint_utils.h
index 43c6784..3f28b5e 100644
--- a/runtime/runtime_support.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ART_RUNTIME_RUNTIME_SUPPORT_H_
-#define ART_RUNTIME_RUNTIME_SUPPORT_H_
+#ifndef ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
+#define ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
 
 #include "class_linker.h"
 #include "common_throws.h"
@@ -42,13 +42,6 @@
 extern "C" void art_quick_proxy_invoke_handler();
 extern "C" void art_work_around_app_jni_bugs();
 
-extern "C" double art_l2d(int64_t l);
-extern "C" float art_l2f(int64_t l);
-extern "C" int64_t art_d2l(double d);
-extern "C" int32_t art_d2i(double d);
-extern "C" int64_t art_f2l(float f);
-extern "C" int32_t art_f2i(float f);
-
 namespace art {
 namespace mirror {
 class Class;
@@ -416,4 +409,4 @@
 
 }  // namespace art
 
-#endif  // ART_RUNTIME_RUNTIME_SUPPORT_H_
+#endif  // ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc
new file mode 100644
index 0000000..98f7b12
--- /dev/null
+++ b/runtime/entrypoints/jni/jni_entrypoints.cc
@@ -0,0 +1,46 @@
+/*
+ * 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 "base/logging.h"
+#include "mirror/abstract_method.h"
+#include "scoped_thread_state_change.h"
+#include "thread.h"
+
+namespace art {
+
+// Used by the JNI dlsym stub to find the native method to invoke if none is registered.
+extern "C" void* artFindNativeMethod(Thread* self) {
+  Locks::mutator_lock_->AssertNotHeld(self);  // We come here as Native.
+  DCHECK(Thread::Current() == self);
+  ScopedObjectAccess soa(self);
+
+  mirror::AbstractMethod* method = self->GetCurrentMethod(NULL);
+  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 = soa.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;
+  }
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/math_entrypoints.cc b/runtime/entrypoints/math_entrypoints.cc
new file mode 100644
index 0000000..31d13c8
--- /dev/null
+++ b/runtime/entrypoints/math_entrypoints.cc
@@ -0,0 +1,89 @@
+/*
+ * 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 "math_entrypoints.h"
+
+namespace art {
+
+extern "C" double art_l2d(int64_t l) {
+  return static_cast<double>(l);
+}
+
+extern "C" float art_l2f(int64_t l) {
+  return static_cast<float>(l);
+}
+
+/*
+ * Float/double conversion requires clamping to min and max of integer form.  If
+ * target doesn't support this normally, use these.
+ */
+extern "C" int64_t art_d2l(double d) {
+  static const double kMaxLong = static_cast<double>(static_cast<int64_t>(0x7fffffffffffffffULL));
+  static const double kMinLong = static_cast<double>(static_cast<int64_t>(0x8000000000000000ULL));
+  if (d >= kMaxLong) {
+    return static_cast<int64_t>(0x7fffffffffffffffULL);
+  } else if (d <= kMinLong) {
+    return static_cast<int64_t>(0x8000000000000000ULL);
+  } else if (d != d)  {  // NaN case
+    return 0;
+  } else {
+    return static_cast<int64_t>(d);
+  }
+}
+
+extern "C" int64_t art_f2l(float f) {
+  static const float kMaxLong = static_cast<float>(static_cast<int64_t>(0x7fffffffffffffffULL));
+  static const float kMinLong = static_cast<float>(static_cast<int64_t>(0x8000000000000000ULL));
+  if (f >= kMaxLong) {
+    return static_cast<int64_t>(0x7fffffffffffffffULL);
+  } else if (f <= kMinLong) {
+    return static_cast<int64_t>(0x8000000000000000ULL);
+  } else if (f != f) {  // NaN case
+    return 0;
+  } else {
+    return static_cast<int64_t>(f);
+  }
+}
+
+extern "C" int32_t art_d2i(double d) {
+  static const double kMaxInt = static_cast<double>(static_cast<int32_t>(0x7fffffffUL));
+  static const double kMinInt = static_cast<double>(static_cast<int32_t>(0x80000000UL));
+  if (d >= kMaxInt) {
+    return static_cast<int32_t>(0x7fffffffUL);
+  } else if (d <= kMinInt) {
+    return static_cast<int32_t>(0x80000000UL);
+  } else if (d != d)  {  // NaN case
+    return 0;
+  } else {
+    return static_cast<int32_t>(d);
+  }
+}
+
+extern "C" int32_t art_f2i(float f) {
+  static const float kMaxInt = static_cast<float>(static_cast<int32_t>(0x7fffffffUL));
+  static const float kMinInt = static_cast<float>(static_cast<int32_t>(0x80000000UL));
+  if (f >= kMaxInt) {
+    return static_cast<int32_t>(0x7fffffffUL);
+  } else if (f <= kMinInt) {
+    return static_cast<int32_t>(0x80000000UL);
+  } else if (f != f) {  // NaN case
+    return 0;
+  } else {
+    return static_cast<int32_t>(f);
+  }
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/math_entrypoints.h b/runtime/entrypoints/math_entrypoints.h
new file mode 100644
index 0000000..717c734
--- /dev/null
+++ b/runtime/entrypoints/math_entrypoints.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ENTRYPOINTS_MATH_ENTRYPOINTS_H_
+#define ART_RUNTIME_ENTRYPOINTS_MATH_ENTRYPOINTS_H_
+
+#include <stdint.h>
+
+extern "C" double art_l2d(int64_t l);
+extern "C" float art_l2f(int64_t l);
+extern "C" int64_t art_d2l(double d);
+extern "C" int32_t art_d2i(double d);
+extern "C" int64_t art_f2l(float f);
+extern "C" int32_t art_f2i(float f);
+
+#endif  // ART_RUNTIME_ENTRYPOINTS_MATH_ENTRYPOINTS_H_
diff --git a/runtime/runtime_support_test.cc b/runtime/entrypoints/math_entrypoints_test.cc
similarity index 89%
rename from runtime/runtime_support_test.cc
rename to runtime/entrypoints/math_entrypoints_test.cc
index b827813..ca8b931 100644
--- a/runtime/runtime_support_test.cc
+++ b/runtime/entrypoints/math_entrypoints_test.cc
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-#include "runtime_support.h"
+#include "math_entrypoints.h"
 
 #include "common_test.h"
 #include <limits>
 
 namespace art {
 
-class RuntimeSupportTest : public CommonTest {};
+class MathEntrypointsTest : public CommonTest {};
 
-TEST_F(RuntimeSupportTest, DoubleToLong) {
+TEST_F(MathEntrypointsTest, DoubleToLong) {
   EXPECT_EQ(std::numeric_limits<int64_t>::max(), art_d2l(1.85e19));
   EXPECT_EQ(std::numeric_limits<int64_t>::min(), art_d2l(-1.85e19));
   EXPECT_EQ(0LL, art_d2l(0));
@@ -35,7 +35,7 @@
   EXPECT_EQ(-100LL, art_d2l(-100.0));
 }
 
-TEST_F(RuntimeSupportTest, FloatToLong) {
+TEST_F(MathEntrypointsTest, FloatToLong) {
   EXPECT_EQ(std::numeric_limits<int64_t>::max(), art_f2l(1.85e19));
   EXPECT_EQ(std::numeric_limits<int64_t>::min(), art_f2l(-1.85e19));
   EXPECT_EQ(0LL, art_f2l(0));
@@ -47,7 +47,7 @@
   EXPECT_EQ(-100LL, art_f2l(-100.0));
 }
 
-TEST_F(RuntimeSupportTest, DoubleToInt) {
+TEST_F(MathEntrypointsTest, DoubleToInt) {
   EXPECT_EQ(std::numeric_limits<int32_t>::max(), art_d2i(4.3e9));
   EXPECT_EQ(std::numeric_limits<int32_t>::min(), art_d2i(-4.3e9));
   EXPECT_EQ(0L, art_d2i(0));
@@ -59,7 +59,7 @@
   EXPECT_EQ(-100L, art_d2i(-100.0));
 }
 
-TEST_F(RuntimeSupportTest, FloatToInt) {
+TEST_F(MathEntrypointsTest, FloatToInt) {
   EXPECT_EQ(std::numeric_limits<int32_t>::max(), art_f2i(4.3e9));
   EXPECT_EQ(std::numeric_limits<int32_t>::min(), art_f2i(-4.3e9));
   EXPECT_EQ(0L, art_f2i(0));
diff --git a/runtime/entrypoints/portable/portable_alloc_entrypoints.cc b/runtime/entrypoints/portable/portable_alloc_entrypoints.cc
new file mode 100644
index 0000000..2869269
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_alloc_entrypoints.cc
@@ -0,0 +1,69 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" mirror::Object* art_portable_alloc_object_from_code(uint32_t type_idx,
+                                                               mirror::AbstractMethod* referrer,
+                                                               Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return AllocObjectFromCode(type_idx, referrer, thread, false);
+}
+
+extern "C" mirror::Object* art_portable_alloc_object_from_code_with_access_check(uint32_t type_idx,
+                                                                                 mirror::AbstractMethod* referrer,
+                                                                                 Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return AllocObjectFromCode(type_idx, referrer, thread, true);
+}
+
+extern "C" mirror::Object* art_portable_alloc_array_from_code(uint32_t type_idx,
+                                                              mirror::AbstractMethod* referrer,
+                                                              uint32_t length,
+                                                              Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return AllocArrayFromCode(type_idx, referrer, length, self, false);
+}
+
+extern "C" mirror::Object* art_portable_alloc_array_from_code_with_access_check(uint32_t type_idx,
+                                                                                mirror::AbstractMethod* referrer,
+                                                                                uint32_t length,
+                                                                                Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return AllocArrayFromCode(type_idx, referrer, length, self, true);
+}
+
+extern "C" mirror::Object* art_portable_check_and_alloc_array_from_code(uint32_t type_idx,
+                                                                        mirror::AbstractMethod* referrer,
+                                                                        uint32_t length,
+                                                                        Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
+}
+
+extern "C" mirror::Object* art_portable_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
+                                                                                          mirror::AbstractMethod* referrer,
+                                                                                          uint32_t length,
+                                                                                          Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_argument_visitor.h b/runtime/entrypoints/portable/portable_argument_visitor.h
new file mode 100644
index 0000000..f268baf
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_argument_visitor.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ARGUMENT_VISITOR_H_
+#define ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ARGUMENT_VISITOR_H_
+
+#include "object_utils.h"
+
+namespace art {
+
+// Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame.
+class PortableArgumentVisitor {
+ public:
+// Offset to first (not the Method*) argument in a Runtime::kRefAndArgs callee save frame.
+// Size of Runtime::kRefAndArgs callee save frame.
+// Size of Method* and register parameters in out stack arguments.
+#if defined(__arm__)
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 8
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 48
+#define PORTABLE_STACK_ARG_SKIP 0
+#elif defined(__mips__)
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64
+#define PORTABLE_STACK_ARG_SKIP 16
+#elif defined(__i386__)
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 32
+#define PORTABLE_STACK_ARG_SKIP 4
+#else
+#error "Unsupported architecture"
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0
+#define PORTABLE_STACK_ARG_SKIP 0
+#endif
+
+  PortableArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
+    caller_mh_(caller_mh),
+    args_in_regs_(ComputeArgsInRegs(caller_mh)),
+    num_params_(caller_mh.NumArgs()),
+    reg_args_(reinterpret_cast<byte*>(sp) + PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET),
+    stack_args_(reinterpret_cast<byte*>(sp) + PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE
+                + PORTABLE_STACK_ARG_SKIP),
+    cur_args_(reg_args_),
+    cur_arg_index_(0),
+    param_index_(0) {
+  }
+
+  virtual ~PortableArgumentVisitor() {}
+
+  virtual void Visit() = 0;
+
+  bool IsParamAReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return caller_mh_.IsParamAReference(param_index_);
+  }
+
+  bool IsParamALongOrDouble() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return caller_mh_.IsParamALongOrDouble(param_index_);
+  }
+
+  Primitive::Type GetParamPrimitiveType() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return caller_mh_.GetParamPrimitiveType(param_index_);
+  }
+
+  byte* GetParamAddress() const {
+    return cur_args_ + (cur_arg_index_ * kPointerSize);
+  }
+
+  void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    for (cur_arg_index_ = 0;  cur_arg_index_ < args_in_regs_ && param_index_ < num_params_; ) {
+#if (defined(__arm__) || defined(__mips__))
+      if (IsParamALongOrDouble() && cur_arg_index_ == 2) {
+        break;
+      }
+#endif
+      Visit();
+      cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
+      param_index_++;
+    }
+    cur_args_ = stack_args_;
+    cur_arg_index_ = 0;
+    while (param_index_ < num_params_) {
+#if (defined(__arm__) || defined(__mips__))
+      if (IsParamALongOrDouble() && cur_arg_index_ % 2 != 0) {
+        cur_arg_index_++;
+      }
+#endif
+      Visit();
+      cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
+      param_index_++;
+    }
+  }
+
+ private:
+  static size_t ComputeArgsInRegs(MethodHelper& mh) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+#if (defined(__i386__))
+    return 0;
+#else
+    size_t args_in_regs = 0;
+    size_t num_params = mh.NumArgs();
+    for (size_t i = 0; i < num_params; i++) {
+      args_in_regs = args_in_regs + (mh.IsParamALongOrDouble(i) ? 2 : 1);
+      if (args_in_regs > 3) {
+        args_in_regs = 3;
+        break;
+      }
+    }
+    return args_in_regs;
+#endif
+  }
+  MethodHelper& caller_mh_;
+  const size_t args_in_regs_;
+  const size_t num_params_;
+  byte* const reg_args_;
+  byte* const stack_args_;
+  byte* cur_args_;
+  size_t cur_arg_index_;
+  size_t param_index_;
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ARGUMENT_VISITOR_H_
diff --git a/runtime/entrypoints/portable/portable_cast_entrypoints.cc b/runtime/entrypoints/portable/portable_cast_entrypoints.cc
new file mode 100644
index 0000000..d343c5d
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_cast_entrypoints.cc
@@ -0,0 +1,57 @@
+/*
+ * 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 "common_throws.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" int32_t art_portable_is_assignable_from_code(const mirror::Class* dest_type,
+                                                        const mirror::Class* src_type)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(dest_type != NULL);
+  DCHECK(src_type != NULL);
+  return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
+}
+
+extern "C" void art_portable_check_cast_from_code(const mirror::Class* dest_type,
+                                                  const mirror::Class* src_type)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
+  DCHECK(src_type->IsClass()) << PrettyClass(src_type);
+  if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
+    ThrowClassCastException(dest_type, src_type);
+  }
+}
+
+extern "C" void art_portable_check_put_array_element_from_code(const mirror::Object* element,
+                                                               const mirror::Object* array)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  if (element == NULL) {
+    return;
+  }
+  DCHECK(array != NULL);
+  mirror::Class* array_class = array->GetClass();
+  DCHECK(array_class != NULL);
+  mirror::Class* component_type = array_class->GetComponentType();
+  mirror::Class* element_class = element->GetClass();
+  if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
+    ThrowArrayStoreException(element_class, array_class);
+  }
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_dexcache_entrypoints.cc b/runtime/entrypoints/portable/portable_dexcache_entrypoints.cc
new file mode 100644
index 0000000..bdab587
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_dexcache_entrypoints.cc
@@ -0,0 +1,53 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "gc/accounting/card_table-inl.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" mirror::Object* art_portable_initialize_static_storage_from_code(uint32_t type_idx,
+                                                                            mirror::AbstractMethod* referrer,
+                                                                            Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false);
+}
+
+extern "C" mirror::Object* art_portable_initialize_type_from_code(uint32_t type_idx,
+                                                                  mirror::AbstractMethod* referrer,
+                                                                  Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false);
+}
+
+extern "C" mirror::Object* art_portable_initialize_type_and_verify_access_from_code(uint32_t type_idx,
+                                                                                    mirror::AbstractMethod* referrer,
+                                                                                    Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  // Called when caller isn't guaranteed to have access to a type and the dex cache may be
+  // unpopulated
+  return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true);
+}
+
+extern "C" mirror::Object* art_portable_resolve_string_from_code(mirror::AbstractMethod* referrer,
+                                                                 uint32_t string_idx)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return ResolveStringFromCode(referrer, string_idx);
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_entrypoints.h b/runtime/entrypoints/portable/portable_entrypoints.h
new file mode 100644
index 0000000..a229c76
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_entrypoints.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ENTRYPOINTS_H_
+#define ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ENTRYPOINTS_H_
+
+#include "dex_file-inl.h"
+#include "runtime.h"
+
+namespace art {
+namespace mirror {
+  class AbstractMethod;
+  class Object;
+}  // namespace mirror
+class Thread;
+
+#define PORTABLE_ENTRYPOINT_OFFSET(x) \
+    (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, portable_entrypoints_)) + \
+        static_cast<uintptr_t>(OFFSETOF_MEMBER(PortableEntryPoints, x)))
+
+// Pointers to functions that are called by code generated by compiler's adhering to the portable
+// compiler ABI.
+struct PACKED(4) PortableEntryPoints {
+  // Invocation
+  const void* (*pPortableResolutionTrampolineFromCode)(mirror::AbstractMethod*, mirror::Object*,
+                                                       mirror::AbstractMethod**, Thread*);
+};
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_ENTRYPOINTS_PORTABLE_PORTABLE_ENTRYPOINTS_H_
diff --git a/runtime/entrypoints/portable/portable_field_entrypoints.cc b/runtime/entrypoints/portable/portable_field_entrypoints.cc
new file mode 100644
index 0000000..aa0f03c
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_field_entrypoints.cc
@@ -0,0 +1,241 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/field-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" int32_t art_portable_set32_static_from_code(uint32_t field_idx,
+                                                       mirror::AbstractMethod* referrer,
+                                                       int32_t new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx,
+                               referrer,
+                               StaticPrimitiveWrite,
+                               sizeof(uint32_t));
+  if (LIKELY(field != NULL)) {
+    field->Set32(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx,
+                            referrer,
+                            Thread::Current(),
+                            StaticPrimitiveWrite,
+                            sizeof(uint32_t),
+                            true);
+  if (LIKELY(field != NULL)) {
+    field->Set32(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_set64_static_from_code(uint32_t field_idx,
+                                                       mirror::AbstractMethod* referrer,
+                                                       int64_t new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t));
+  if (LIKELY(field != NULL)) {
+    field->Set64(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx,
+                            referrer,
+                            Thread::Current(),
+                            StaticPrimitiveWrite,
+                            sizeof(uint64_t),
+                            true);
+  if (LIKELY(field != NULL)) {
+    field->Set64(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_set_obj_static_from_code(uint32_t field_idx,
+                                                         mirror::AbstractMethod* referrer,
+                                                         mirror::Object* new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite,
+                                       sizeof(mirror::Object*));
+  if (LIKELY(field != NULL)) {
+    field->SetObj(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            StaticObjectWrite, sizeof(mirror::Object*), true);
+  if (LIKELY(field != NULL)) {
+    field->SetObj(field->GetDeclaringClass(), new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_get32_static_from_code(uint32_t field_idx,
+                                                       mirror::AbstractMethod* referrer)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get32(field->GetDeclaringClass());
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            StaticPrimitiveRead, sizeof(uint32_t), true);
+  if (LIKELY(field != NULL)) {
+    return field->Get32(field->GetDeclaringClass());
+  }
+  return 0;
+}
+
+extern "C" int64_t art_portable_get64_static_from_code(uint32_t field_idx,
+                                                       mirror::AbstractMethod* referrer)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get64(field->GetDeclaringClass());
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            StaticPrimitiveRead, sizeof(uint64_t), true);
+  if (LIKELY(field != NULL)) {
+    return field->Get64(field->GetDeclaringClass());
+  }
+  return 0;
+}
+
+extern "C" mirror::Object* art_portable_get_obj_static_from_code(uint32_t field_idx,
+                                                                 mirror::AbstractMethod* referrer)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead,
+                                       sizeof(mirror::Object*));
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(field->GetDeclaringClass());
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            StaticObjectRead, sizeof(mirror::Object*), true);
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(field->GetDeclaringClass());
+  }
+  return 0;
+}
+
+extern "C" int32_t art_portable_set32_instance_from_code(uint32_t field_idx,
+                                                         mirror::AbstractMethod* referrer,
+                                                         mirror::Object* obj, uint32_t new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t));
+  if (LIKELY(field != NULL)) {
+    field->Set32(obj, new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstancePrimitiveWrite, sizeof(uint32_t), true);
+  if (LIKELY(field != NULL)) {
+    field->Set32(obj, new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_set64_instance_from_code(uint32_t field_idx,
+                                                         mirror::AbstractMethod* referrer,
+                                                         mirror::Object* obj, int64_t new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t));
+  if (LIKELY(field != NULL)) {
+    field->Set64(obj, new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstancePrimitiveWrite, sizeof(uint64_t), true);
+  if (LIKELY(field != NULL)) {
+    field->Set64(obj, new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_set_obj_instance_from_code(uint32_t field_idx,
+                                                           mirror::AbstractMethod* referrer,
+                                                           mirror::Object* obj,
+                                                           mirror::Object* new_value)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite,
+                                       sizeof(mirror::Object*));
+  if (LIKELY(field != NULL)) {
+    field->SetObj(obj, new_value);
+    return 0;
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstanceObjectWrite, sizeof(mirror::Object*), true);
+  if (LIKELY(field != NULL)) {
+    field->SetObj(obj, new_value);
+    return 0;
+  }
+  return -1;
+}
+
+extern "C" int32_t art_portable_get32_instance_from_code(uint32_t field_idx,
+                                                         mirror::AbstractMethod* referrer,
+                                                         mirror::Object* obj)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get32(obj);
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstancePrimitiveRead, sizeof(uint32_t), true);
+  if (LIKELY(field != NULL)) {
+    return field->Get32(obj);
+  }
+  return 0;
+}
+
+extern "C" int64_t art_portable_get64_instance_from_code(uint32_t field_idx,
+                                                         mirror::AbstractMethod* referrer,
+                                                         mirror::Object* obj)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t));
+  if (LIKELY(field != NULL)) {
+    return field->Get64(obj);
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstancePrimitiveRead, sizeof(uint64_t), true);
+  if (LIKELY(field != NULL)) {
+    return field->Get64(obj);
+  }
+  return 0;
+}
+
+extern "C" mirror::Object* art_portable_get_obj_instance_from_code(uint32_t field_idx,
+                                                                   mirror::AbstractMethod* referrer,
+                                                                   mirror::Object* obj)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead,
+                                       sizeof(mirror::Object*));
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(obj);
+  }
+  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+                            InstanceObjectRead, sizeof(mirror::Object*), true);
+  if (LIKELY(field != NULL)) {
+    return field->GetObj(obj);
+  }
+  return 0;
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc b/runtime/entrypoints/portable/portable_fillarray_entrypoints.cc
new file mode 100644
index 0000000..771608b
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_fillarray_entrypoints.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 "dex_instruction.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" void art_portable_fill_array_data_from_code(mirror::AbstractMethod* method,
+                                                       uint32_t dex_pc,
+                                                       mirror::Array* array,
+                                                       uint32_t payload_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem();
+  const Instruction::ArrayDataPayload* payload =
+      reinterpret_cast<const Instruction::ArrayDataPayload*>(code_item->insns_ + payload_offset);
+  DCHECK_EQ(payload->ident, static_cast<uint16_t>(Instruction::kArrayDataSignature));
+  if (UNLIKELY(array == NULL)) {
+    ThrowNullPointerException(NULL, "null array in FILL_ARRAY_DATA");
+    return;  // Error
+  }
+  DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
+  if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
+    Thread* self = Thread::Current();
+    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+    self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
+                             "failed FILL_ARRAY_DATA; length=%d, index=%d",
+                             array->GetLength(), payload->element_count - 1);
+    return;  // Error
+  }
+  uint32_t size_in_bytes = payload->element_count * payload->element_width;
+  memcpy(array->GetRawData(payload->element_width), payload->data, size_in_bytes);
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_invoke_entrypoints.cc b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
new file mode 100644
index 0000000..5911ba3
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_invoke_entrypoints.cc
@@ -0,0 +1,104 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/dex_cache-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+static mirror::AbstractMethod* FindMethodHelper(uint32_t method_idx,
+                                                mirror::Object* this_object,
+                                                mirror::AbstractMethod* caller_method,
+                                                bool access_check,
+                                                InvokeType type,
+                                                Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  mirror::AbstractMethod* method = FindMethodFast(method_idx,
+                                                  this_object,
+                                                  caller_method,
+                                                  access_check,
+                                                  type);
+  if (UNLIKELY(method == NULL)) {
+    method = FindMethodFromCode(method_idx, this_object, caller_method,
+                                thread, access_check, type);
+    if (UNLIKELY(method == NULL)) {
+      CHECK(thread->IsExceptionPending());
+      return 0;  // failure
+    }
+  }
+  DCHECK(!thread->IsExceptionPending());
+  const void* code = method->GetEntryPointFromCompiledCode();
+
+  // When we return, the caller will branch to this address, so it had better not be 0!
+  if (UNLIKELY(code == NULL)) {
+      MethodHelper mh(method);
+      LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
+                 << " location: " << mh.GetDexFile().GetLocation();
+  }
+  return method;
+}
+
+extern "C" mirror::Object* art_portable_find_static_method_from_code_with_access_check(uint32_t method_idx,
+                                                                                       mirror::Object* this_object,
+                                                                                       mirror::AbstractMethod* referrer,
+                                                                                       Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread);
+}
+
+extern "C" mirror::Object* art_portable_find_direct_method_from_code_with_access_check(uint32_t method_idx,
+                                                                                       mirror::Object* this_object,
+                                                                                       mirror::AbstractMethod* referrer,
+                                                                                       Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread);
+}
+
+extern "C" mirror::Object* art_portable_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
+                                                                                        mirror::Object* this_object,
+                                                                                        mirror::AbstractMethod* referrer,
+                                                                                        Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread);
+}
+
+extern "C" mirror::Object* art_portable_find_super_method_from_code_with_access_check(uint32_t method_idx,
+                                                                                      mirror::Object* this_object,
+                                                                                      mirror::AbstractMethod* referrer,
+                                                                                      Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread);
+}
+
+extern "C" mirror::Object* art_portable_find_interface_method_from_code_with_access_check(uint32_t method_idx,
+                                                                                          mirror::Object* this_object,
+                                                                                          mirror::AbstractMethod* referrer,
+                                                                                          Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread);
+}
+
+extern "C" mirror::Object* art_portable_find_interface_method_from_code(uint32_t method_idx,
+                                                                        mirror::Object* this_object,
+                                                                        mirror::AbstractMethod* referrer,
+                                                                        Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread);
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_jni_entrypoints.cc b/runtime/entrypoints/portable/portable_jni_entrypoints.cc
new file mode 100644
index 0000000..8df16ae
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_jni_entrypoints.cc
@@ -0,0 +1,98 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+#include "thread-inl.h"
+
+namespace art {
+
+// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
+extern "C" uint32_t art_portable_jni_method_start(Thread* self)
+    UNLOCK_FUNCTION(GlobalSynchronizatio::mutator_lock_) {
+  JNIEnvExt* env = self->GetJniEnv();
+  uint32_t saved_local_ref_cookie = env->local_ref_cookie;
+  env->local_ref_cookie = env->locals.GetSegmentState();
+  self->TransitionFromRunnableToSuspended(kNative);
+  return saved_local_ref_cookie;
+}
+
+extern "C" uint32_t art_portable_jni_method_start_synchronized(jobject to_lock, Thread* self)
+    UNLOCK_FUNCTION(Locks::mutator_lock_) {
+  self->DecodeJObject(to_lock)->MonitorEnter(self);
+  return art_portable_jni_method_start(self);
+}
+
+static void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
+  JNIEnvExt* env = self->GetJniEnv();
+  env->locals.SetSegmentState(env->local_ref_cookie);
+  env->local_ref_cookie = saved_local_ref_cookie;
+}
+
+extern "C" void art_portable_jni_method_end(uint32_t saved_local_ref_cookie, Thread* self)
+    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
+  self->TransitionFromSuspendedToRunnable();
+  PopLocalReferences(saved_local_ref_cookie, self);
+}
+
+
+extern "C" void art_portable_jni_method_end_synchronized(uint32_t saved_local_ref_cookie,
+                                              jobject locked,
+                                              Thread* self)
+    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
+  self->TransitionFromSuspendedToRunnable();
+  UnlockJniSynchronizedMethod(locked, self);  // Must decode before pop.
+  PopLocalReferences(saved_local_ref_cookie, self);
+}
+
+extern "C" mirror::Object* art_portable_jni_method_end_with_reference(jobject result,
+                                                                      uint32_t saved_local_ref_cookie,
+                                                                      Thread* self)
+    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
+  self->TransitionFromSuspendedToRunnable();
+  mirror::Object* o = self->DecodeJObject(result);  // Must decode before pop.
+  PopLocalReferences(saved_local_ref_cookie, self);
+  // Process result.
+  if (UNLIKELY(self->GetJniEnv()->check_jni)) {
+    if (self->IsExceptionPending()) {
+      return NULL;
+    }
+    CheckReferenceResult(o, self);
+  }
+  return o;
+}
+
+extern "C" mirror::Object* art_portable_jni_method_end_with_reference_synchronized(jobject result,
+                                                                                   uint32_t saved_local_ref_cookie,
+                                                                                   jobject locked,
+                                                                                   Thread* self)
+    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
+  self->TransitionFromSuspendedToRunnable();
+  UnlockJniSynchronizedMethod(locked, self);  // Must decode before pop.
+  mirror::Object* o = self->DecodeJObject(result);
+  PopLocalReferences(saved_local_ref_cookie, self);
+  // Process result.
+  if (UNLIKELY(self->GetJniEnv()->check_jni)) {
+    if (self->IsExceptionPending()) {
+      return NULL;
+    }
+    CheckReferenceResult(o, self);
+  }
+  return o;
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_lock_entrypoints.cc b/runtime/entrypoints/portable/portable_lock_entrypoints.cc
new file mode 100644
index 0000000..44d3da9
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_lock_entrypoints.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 "entrypoints/entrypoint_utils.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" void art_portable_lock_object_from_code(mirror::Object* obj, Thread* thread)
+    EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) {
+  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());
+}
+
+extern "C" void art_portable_unlock_object_from_code(mirror::Object* obj, Thread* thread)
+    UNLOCK_FUNCTION(monitor_lock_) {
+  DCHECK(obj != NULL);  // Assumed to have been checked before entry.
+  // MonitorExit may throw exception.
+  obj->MonitorExit(thread);
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_proxy_entrypoints.cc b/runtime/entrypoints/portable/portable_proxy_entrypoints.cc
new file mode 100644
index 0000000..3db39cd
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_proxy_entrypoints.cc
@@ -0,0 +1,109 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+#include "portable_argument_visitor.h"
+#include "scoped_thread_state_change.h"
+
+namespace art {
+
+// Visits arguments on the stack placing them into the args vector, Object* arguments are converted
+// to jobjects.
+class BuildPortableArgumentVisitor : public PortableArgumentVisitor {
+ public:
+  BuildPortableArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp,
+                               ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) :
+    PortableArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {}
+
+  virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    jvalue val;
+    Primitive::Type type = GetParamPrimitiveType();
+    switch (type) {
+      case Primitive::kPrimNot: {
+        mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress());
+        val.l = soa_.AddLocalReference<jobject>(obj);
+        break;
+      }
+      case Primitive::kPrimLong:  // Fall-through.
+      case Primitive::kPrimDouble:
+        val.j = *reinterpret_cast<jlong*>(GetParamAddress());
+        break;
+      case Primitive::kPrimBoolean:  // Fall-through.
+      case Primitive::kPrimByte:     // Fall-through.
+      case Primitive::kPrimChar:     // Fall-through.
+      case Primitive::kPrimShort:    // Fall-through.
+      case Primitive::kPrimInt:      // Fall-through.
+      case Primitive::kPrimFloat:
+        val.i =  *reinterpret_cast<jint*>(GetParamAddress());
+        break;
+      case Primitive::kPrimVoid:
+        LOG(FATAL) << "UNREACHABLE";
+        val.j = 0;
+        break;
+    }
+    args_.push_back(val);
+  }
+
+ private:
+  ScopedObjectAccessUnchecked& soa_;
+  std::vector<jvalue>& args_;
+
+  DISALLOW_COPY_AND_ASSIGN(BuildPortableArgumentVisitor);
+};
+
+// 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 place into jobjects the
+// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
+// field within the proxy object, which will box the primitive arguments and deal with error cases.
+extern "C" uint64_t artPortableProxyInvokeHandler(mirror::AbstractMethod* proxy_method,
+                                                  mirror::Object* receiver,
+                                                  Thread* self, mirror::AbstractMethod** sp)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
+  const char* old_cause =
+      self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
+  self->VerifyStack();
+  // Start new JNI local reference state.
+  JNIEnvExt* env = self->GetJniEnv();
+  ScopedObjectAccessUnchecked soa(env);
+  ScopedJniEnvLocalRefState env_state(env);
+  // Create local ref. copies of proxy method and the receiver.
+  jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
+
+  // Placing arguments into args vector and remove the receiver.
+  MethodHelper proxy_mh(proxy_method);
+  std::vector<jvalue> args;
+  BuildPortableArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args);
+  local_ref_visitor.VisitArguments();
+  args.erase(args.begin());
+
+  // Convert proxy method into expected interface method.
+  mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
+  DCHECK(interface_method != NULL);
+  DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
+  jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
+
+  // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
+  // that performs allocations.
+  self->EndAssertNoThreadSuspension(old_cause);
+  JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(),
+                                               rcvr_jobj, interface_method_jobj, args);
+  return result.GetJ();
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_stub_entrypoints.cc b/runtime/entrypoints/portable/portable_stub_entrypoints.cc
new file mode 100644
index 0000000..c510c65
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_stub_entrypoints.cc
@@ -0,0 +1,145 @@
+/*
+ * 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 "dex_instruction-inl.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+// Lazily resolve a method for portable. Called by stub code.
+extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
+                                                       mirror::Object* receiver,
+                                                       mirror::AbstractMethod** called_addr,
+                                                       Thread* thread)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  uint32_t dex_pc;
+  mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
+
+  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  InvokeType invoke_type;
+  bool is_range;
+  if (called->IsRuntimeMethod()) {
+    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();
+    switch (instr_code) {
+      case Instruction::INVOKE_DIRECT:
+        invoke_type = kDirect;
+        is_range = false;
+        break;
+      case Instruction::INVOKE_DIRECT_RANGE:
+        invoke_type = kDirect;
+        is_range = true;
+        break;
+      case Instruction::INVOKE_STATIC:
+        invoke_type = kStatic;
+        is_range = false;
+        break;
+      case Instruction::INVOKE_STATIC_RANGE:
+        invoke_type = kStatic;
+        is_range = true;
+        break;
+      case Instruction::INVOKE_SUPER:
+        invoke_type = kSuper;
+        is_range = false;
+        break;
+      case Instruction::INVOKE_SUPER_RANGE:
+        invoke_type = kSuper;
+        is_range = true;
+        break;
+      case Instruction::INVOKE_VIRTUAL:
+        invoke_type = kVirtual;
+        is_range = false;
+        break;
+      case Instruction::INVOKE_VIRTUAL_RANGE:
+        invoke_type = kVirtual;
+        is_range = true;
+        break;
+      case Instruction::INVOKE_INTERFACE:
+        invoke_type = kInterface;
+        is_range = false;
+        break;
+      case Instruction::INVOKE_INTERFACE_RANGE:
+        invoke_type = kInterface;
+        is_range = true;
+        break;
+      default:
+        LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
+        // Avoid used uninitialized warnings.
+        invoke_type = kDirect;
+        is_range = true;
+    }
+    uint32_t dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
+    called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
+    // Refine called method based on receiver.
+    if (invoke_type == kVirtual) {
+      called = receiver->GetClass()->FindVirtualMethodForVirtual(called);
+    } else if (invoke_type == kInterface) {
+      called = receiver->GetClass()->FindVirtualMethodForInterface(called);
+    }
+  } else {
+    CHECK(called->IsStatic()) << PrettyMethod(called);
+    invoke_type = kStatic;
+  }
+  const void* code = NULL;
+  if (LIKELY(!thread->IsExceptionPending())) {
+    // Incompatible class change should have been handled in resolve method.
+    CHECK(!called->CheckIncompatibleClassChange(invoke_type));
+    // Ensure that the called method's class is initialized.
+    mirror::Class* called_class = called->GetDeclaringClass();
+    linker->EnsureInitialized(called_class, true, true);
+    if (LIKELY(called_class->IsInitialized())) {
+      code = called->GetEntryPointFromCompiledCode();
+      // TODO: remove this after we solve the link issue.
+      {  // for lazy link.
+        if (code == NULL) {
+          code = linker->GetOatCodeFor(called);
+        }
+      }
+    } else if (called_class->IsInitializing()) {
+      if (invoke_type == kStatic) {
+        // 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->GetEntryPointFromCompiledCode();
+        // TODO: remove this after we solve the link issue.
+        {  // for lazy link.
+          if (code == NULL) {
+            code = linker->GetOatCodeFor(called);
+          }
+        }
+      }
+    } else {
+      DCHECK(called_class->IsErroneous());
+    }
+  }
+  if (LIKELY(code != NULL)) {
+    // Expect class to at least be initializing.
+    DCHECK(called->GetDeclaringClass()->IsInitializing());
+    // Don't want infinite recursion.
+    DCHECK(code != GetResolutionTrampoline(linker));
+    // Set up entry into main method
+    *called_addr = called;
+  }
+  return code;
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_thread_entrypoints.cc b/runtime/entrypoints/portable/portable_thread_entrypoints.cc
new file mode 100644
index 0000000..dac7388
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_thread_entrypoints.cc
@@ -0,0 +1,99 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method.h"
+#include "mirror/object-inl.h"
+#include "verifier/dex_gc_map.h"
+#include "stack.h"
+
+namespace art {
+
+class ShadowFrameCopyVisitor : public StackVisitor {
+ public:
+  explicit ShadowFrameCopyVisitor(Thread* self) : StackVisitor(self, NULL), prev_frame_(NULL),
+      top_frame_(NULL) {}
+
+  bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    if (IsShadowFrame()) {
+      ShadowFrame* cur_frame = GetCurrentShadowFrame();
+      size_t num_regs = cur_frame->NumberOfVRegs();
+      mirror::AbstractMethod* method = cur_frame->GetMethod();
+      uint32_t dex_pc = cur_frame->GetDexPC();
+      ShadowFrame* new_frame = ShadowFrame::Create(num_regs, NULL, method, dex_pc);
+
+      const uint8_t* gc_map = method->GetNativeGcMap();
+      uint32_t gc_map_length = static_cast<uint32_t>((gc_map[0] << 24) |
+                                                     (gc_map[1] << 16) |
+                                                     (gc_map[2] << 8) |
+                                                     (gc_map[3] << 0));
+      verifier::DexPcToReferenceMap dex_gc_map(gc_map + 4, gc_map_length);
+      const uint8_t* reg_bitmap = dex_gc_map.FindBitMap(dex_pc);
+      for (size_t reg = 0; reg < num_regs; ++reg) {
+        if (TestBitmap(reg, reg_bitmap)) {
+          new_frame->SetVRegReference(reg, cur_frame->GetVRegReference(reg));
+        } else {
+          new_frame->SetVReg(reg, cur_frame->GetVReg(reg));
+        }
+      }
+
+      if (prev_frame_ != NULL) {
+        prev_frame_->SetLink(new_frame);
+      } else {
+        top_frame_ = new_frame;
+      }
+      prev_frame_ = new_frame;
+    }
+    return true;
+  }
+
+  ShadowFrame* GetShadowFrameCopy() {
+    return top_frame_;
+  }
+
+ private:
+  static bool TestBitmap(int reg, const uint8_t* reg_vector) {
+    return ((reg_vector[reg / 8] >> (reg % 8)) & 0x01) != 0;
+  }
+
+  ShadowFrame* prev_frame_;
+  ShadowFrame* top_frame_;
+};
+
+extern "C" void art_portable_test_suspend_from_code(Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  CheckSuspend(self);
+  if (Runtime::Current()->GetInstrumentation()->ShouldPortableCodeDeoptimize()) {
+    // Save out the shadow frame to the heap
+    ShadowFrameCopyVisitor visitor(self);
+    visitor.WalkStack(true);
+    self->SetDeoptimizationShadowFrame(visitor.GetShadowFrameCopy());
+    self->SetDeoptimizationReturnValue(JValue());
+    self->SetException(ThrowLocation(), reinterpret_cast<mirror::Throwable*>(-1));
+  }
+}
+
+extern "C" ShadowFrame* art_portable_push_shadow_frame_from_code(Thread* thread,
+                                                                 ShadowFrame* new_shadow_frame,
+                                                                 mirror::AbstractMethod* method,
+                                                                 uint32_t num_vregs) {
+  ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
+  new_shadow_frame->SetMethod(method);
+  new_shadow_frame->SetNumberOfVRegs(num_vregs);
+  return old_frame;
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/portable/portable_throw_entrypoints.cc b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
new file mode 100644
index 0000000..4b2b46b
--- /dev/null
+++ b/runtime/entrypoints/portable/portable_throw_entrypoints.cc
@@ -0,0 +1,123 @@
+/*
+ * 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 "entrypoints/entrypoint_utils.h"
+#include "mirror/abstract_method-inl.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+
+extern "C" void art_portable_throw_div_zero_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ThrowArithmeticExceptionDivideByZero();
+}
+
+extern "C" void art_portable_throw_array_bounds_from_code(int32_t index, int32_t length)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ThrowArrayIndexOutOfBoundsException(index, length);
+}
+
+extern "C" void art_portable_throw_no_such_method_from_code(int32_t method_idx)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ThrowNoSuchMethodError(method_idx);
+}
+
+extern "C" void art_portable_throw_null_pointer_exception_from_code(uint32_t dex_pc)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  // TODO: remove dex_pc argument from caller.
+  UNUSED(dex_pc);
+  Thread* self = Thread::Current();
+  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+  ThrowNullPointerExceptionFromDexPC(throw_location);
+}
+
+extern "C" void art_portable_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  ThrowStackOverflowError(Thread::Current());
+}
+
+extern "C" void art_portable_throw_exception_from_code(mirror::Throwable* exception)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  Thread* self = Thread::Current();
+  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+  if (exception == NULL) {
+    ThrowNullPointerException(NULL, "throw with null exception");
+  } else {
+    self->SetException(throw_location, exception);
+  }
+}
+
+extern "C" void* art_portable_get_and_clear_exception(Thread* self)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  DCHECK(self->IsExceptionPending());
+  // TODO: make this inline.
+  mirror::Throwable* exception = self->GetException(NULL);
+  self->ClearException();
+  return exception;
+}
+
+extern "C" int32_t art_portable_find_catch_block_from_code(mirror::AbstractMethod* current_method,
+                                                           uint32_t ti_offset)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  Thread* self = Thread::Current();  // TODO: make an argument.
+  ThrowLocation throw_location;
+  mirror::Throwable* exception = self->GetException(&throw_location);
+  // Check for special deoptimization exception.
+  if (UNLIKELY(reinterpret_cast<int32_t>(exception) == -1)) {
+    return -1;
+  }
+  mirror::Class* exception_type = exception->GetClass();
+  MethodHelper mh(current_method);
+  const DexFile::CodeItem* code_item = mh.GetCodeItem();
+  DCHECK_LT(ti_offset, code_item->tries_size_);
+  const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
+
+  int iter_index = 0;
+  int result = -1;
+  uint32_t catch_dex_pc = -1;
+  // Iterate over the catch handlers associated with dex_pc
+  for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
+    uint16_t iter_type_idx = it.GetHandlerTypeIndex();
+    // Catch all case
+    if (iter_type_idx == DexFile::kDexNoIndex16) {
+      catch_dex_pc = it.GetHandlerAddress();
+      result = iter_index;
+      break;
+    }
+    // Does this catch exception type apply?
+    mirror::Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
+    if (UNLIKELY(iter_exception_type == NULL)) {
+      // TODO: check, the verifier (class linker?) should take care of resolving all exception
+      //       classes early.
+      LOG(WARNING) << "Unresolved exception class when finding catch block: "
+          << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
+    } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
+      catch_dex_pc = it.GetHandlerAddress();
+      result = iter_index;
+      break;
+    }
+    ++iter_index;
+  }
+  if (result != -1) {
+    // Handler found.
+    Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent(self,
+                                                                   throw_location,
+                                                                   current_method,
+                                                                   catch_dex_pc,
+                                                                   exception);
+  }
+  return result;
+}
+
+}  // namespace art
diff --git a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
index f66fc84..9ed802a 100644
--- a/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_alloc_entrypoints.cc
@@ -15,11 +15,11 @@
  */
 
 #include "callee_save_frame.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/class-inl.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
-#include "runtime_support.h"
 
 namespace art {
 
diff --git a/runtime/entrypoints/quick/quick_argument_visitor.h b/runtime/entrypoints/quick/quick_argument_visitor.h
index 4f81151..35fa972 100644
--- a/runtime/entrypoints/quick/quick_argument_visitor.h
+++ b/runtime/entrypoints/quick/quick_argument_visitor.h
@@ -22,116 +22,6 @@
 namespace art {
 
 // Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame.
-class PortableArgumentVisitor {
- public:
-// Offset to first (not the Method*) argument in a Runtime::kRefAndArgs callee save frame.
-// Size of Runtime::kRefAndArgs callee save frame.
-// Size of Method* and register parameters in out stack arguments.
-#if defined(__arm__)
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 8
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 48
-#define PORTABLE_STACK_ARG_SKIP 0
-#elif defined(__mips__)
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64
-#define PORTABLE_STACK_ARG_SKIP 16
-#elif defined(__i386__)
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 32
-#define PORTABLE_STACK_ARG_SKIP 4
-#else
-#error "Unsupported architecture"
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0
-#define PORTABLE_STACK_ARG_SKIP 0
-#endif
-
-  PortableArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
-    caller_mh_(caller_mh),
-    args_in_regs_(ComputeArgsInRegs(caller_mh)),
-    num_params_(caller_mh.NumArgs()),
-    reg_args_(reinterpret_cast<byte*>(sp) + PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET),
-    stack_args_(reinterpret_cast<byte*>(sp) + PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE
-                + PORTABLE_STACK_ARG_SKIP),
-    cur_args_(reg_args_),
-    cur_arg_index_(0),
-    param_index_(0) {
-  }
-
-  virtual ~PortableArgumentVisitor() {}
-
-  virtual void Visit() = 0;
-
-  bool IsParamAReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return caller_mh_.IsParamAReference(param_index_);
-  }
-
-  bool IsParamALongOrDouble() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return caller_mh_.IsParamALongOrDouble(param_index_);
-  }
-
-  Primitive::Type GetParamPrimitiveType() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return caller_mh_.GetParamPrimitiveType(param_index_);
-  }
-
-  byte* GetParamAddress() const {
-    return cur_args_ + (cur_arg_index_ * kPointerSize);
-  }
-
-  void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    for (cur_arg_index_ = 0;  cur_arg_index_ < args_in_regs_ && param_index_ < num_params_; ) {
-#if (defined(__arm__) || defined(__mips__))
-      if (IsParamALongOrDouble() && cur_arg_index_ == 2) {
-        break;
-      }
-#endif
-      Visit();
-      cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
-      param_index_++;
-    }
-    cur_args_ = stack_args_;
-    cur_arg_index_ = 0;
-    while (param_index_ < num_params_) {
-#if (defined(__arm__) || defined(__mips__))
-      if (IsParamALongOrDouble() && cur_arg_index_ % 2 != 0) {
-        cur_arg_index_++;
-      }
-#endif
-      Visit();
-      cur_arg_index_ += (IsParamALongOrDouble() ? 2 : 1);
-      param_index_++;
-    }
-  }
-
- private:
-  static size_t ComputeArgsInRegs(MethodHelper& mh) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-#if (defined(__i386__))
-    return 0;
-#else
-    size_t args_in_regs = 0;
-    size_t num_params = mh.NumArgs();
-    for (size_t i = 0; i < num_params; i++) {
-      args_in_regs = args_in_regs + (mh.IsParamALongOrDouble(i) ? 2 : 1);
-      if (args_in_regs > 3) {
-        args_in_regs = 3;
-        break;
-      }
-    }
-    return args_in_regs;
-#endif
-  }
-  MethodHelper& caller_mh_;
-  const size_t args_in_regs_;
-  const size_t num_params_;
-  byte* const reg_args_;
-  byte* const stack_args_;
-  byte* cur_args_;
-  size_t cur_arg_index_;
-  size_t param_index_;
-};
-
-// Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame.
 class QuickArgumentVisitor {
  public:
 // Offset to first (not the Method*) argument in a Runtime::kRefAndArgs callee save frame.
diff --git a/runtime/entrypoints/quick/quick_cast_entrypoints.cc b/runtime/entrypoints/quick/quick_cast_entrypoints.cc
index fe91e61..b810bb7 100644
--- a/runtime/entrypoints/quick/quick_cast_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_cast_entrypoints.cc
@@ -15,10 +15,10 @@
  */
 
 #include "callee_save_frame.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
-#include "runtime_support.h"
 
 namespace art {
 
diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
index 0af7a62..6400161b 100644
--- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc
@@ -15,13 +15,13 @@
  */
 
 #include "callee_save_frame.h"
-#include "gc/accounting/card_table-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "class_linker-inl.h"
 #include "dex_file-inl.h"
+#include "gc/accounting/card_table-inl.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
-#include "runtime_support.h"
 
 namespace art {
 
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index 8692e92..74b8cfd 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -20,15 +20,15 @@
 #include "dex_file-inl.h"
 #include "runtime.h"
 
-#define ENTRYPOINT_OFFSET(x) \
-    (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, entrypoints_)) + \
+#define QUICK_ENTRYPOINT_OFFSET(x) \
+    (static_cast<uintptr_t>(OFFSETOF_MEMBER(Thread, quick_entrypoints_)) + \
         static_cast<uintptr_t>(OFFSETOF_MEMBER(QuickEntryPoints, x)))
 
 namespace art {
 namespace mirror {
-class AbstractMethod;
-class Class;
-class Object;
+  class AbstractMethod;
+  class Class;
+  class Object;
 }  // namespace mirror
 class DvmDex;
 class MethodHelper;
@@ -123,8 +123,6 @@
   void* (*pMemcpy)(void*, const void*, size_t);
 
   // Invocation
-  const void* (*pPortableResolutionTrampolineFromCode)(mirror::AbstractMethod*, mirror::Object*,
-                                                       mirror::AbstractMethod**, Thread*);
   const void* (*pQuickResolutionTrampolineFromCode)(mirror::AbstractMethod*, mirror::Object*,
                                                     mirror::AbstractMethod**, Thread*);
   void (*pInvokeDirectTrampolineWithAccessCheck)(uint32_t, void*);
@@ -167,9 +165,6 @@
                                                              jobject locked, Thread* self)
     SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR;
 
-// Initialize an entry point data structure, architecture specific.
-void InitEntryPoints(QuickEntryPoints* points);
-
 }  // namespace art
 
 #endif  // ART_RUNTIME_ENTRYPOINTS_QUICK_QUICK_ENTRYPOINTS_H_
diff --git a/runtime/entrypoints/quick/quick_field_entrypoints.cc b/runtime/entrypoints/quick/quick_field_entrypoints.cc
index c20326c..a4e9dc9 100644
--- a/runtime/entrypoints/quick/quick_field_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_field_entrypoints.cc
@@ -16,10 +16,10 @@
 
 #include "callee_save_frame.h"
 #include "dex_file-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/field-inl.h"
-#include "runtime_support.h"
 
 #include <stdint.h>
 
diff --git a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
index a0b06fb..b81ad12 100644
--- a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
@@ -52,7 +52,7 @@
     ThrowLocation throw_location = self->GetCurrentLocationForThrow();
     self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
                              "failed FILL_ARRAY_DATA; length=%d, index=%d",
-                             array->GetLength(), payload->element_count);
+                             array->GetLength(), payload->element_count - 1);
     return -1;  // Error
   }
   uint32_t size_in_bytes = payload->element_count * payload->element_width;
diff --git a/runtime/entrypoints/quick/quick_invoke_entrypoints.cc b/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
index 6a95f3c..53b3628 100644
--- a/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_invoke_entrypoints.cc
@@ -16,12 +16,12 @@
 
 #include "callee_save_frame.h"
 #include "dex_instruction-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/class-inl.h"
 #include "mirror/dex_cache-inl.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
-#include "runtime_support.h"
 
 namespace art {
 
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index 2d31160..23a28f9 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -15,13 +15,13 @@
  */
 
 #include "dex_file-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/class-inl.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/object.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "object_utils.h"
-#include "runtime_support.h"
 #include "scoped_thread_state_change.h"
 #include "thread.h"
 
diff --git a/runtime/entrypoints/quick/quick_proxy_entrypoints.cc b/runtime/entrypoints/quick/quick_proxy_entrypoints.cc
index e4ef45f..4e3d749 100644
--- a/runtime/entrypoints/quick/quick_proxy_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_proxy_entrypoints.cc
@@ -16,12 +16,12 @@
 
 #include "quick_argument_visitor.h"
 #include "dex_file-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/abstract_method-inl.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/object-inl.h"
 #include "object_utils.h"
 #include "reflection.h"
-#include "runtime_support.h"
 #include "scoped_thread_state_change.h"
 #include "thread.h"
 #include "well_known_classes.h"
@@ -32,50 +32,6 @@
 
 // Visits arguments on the stack placing them into the args vector, Object* arguments are converted
 // to jobjects.
-class BuildPortableArgumentVisitor : public PortableArgumentVisitor {
- public:
-  BuildPortableArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp,
-                               ScopedObjectAccessUnchecked& soa, std::vector<jvalue>& args) :
-    PortableArgumentVisitor(caller_mh, sp), soa_(soa), args_(args) {}
-
-  virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    jvalue val;
-    Primitive::Type type = GetParamPrimitiveType();
-    switch (type) {
-      case Primitive::kPrimNot: {
-        mirror::Object* obj = *reinterpret_cast<mirror::Object**>(GetParamAddress());
-        val.l = soa_.AddLocalReference<jobject>(obj);
-        break;
-      }
-      case Primitive::kPrimLong:  // Fall-through.
-      case Primitive::kPrimDouble:
-        val.j = *reinterpret_cast<jlong*>(GetParamAddress());
-        break;
-      case Primitive::kPrimBoolean:  // Fall-through.
-      case Primitive::kPrimByte:     // Fall-through.
-      case Primitive::kPrimChar:     // Fall-through.
-      case Primitive::kPrimShort:    // Fall-through.
-      case Primitive::kPrimInt:      // Fall-through.
-      case Primitive::kPrimFloat:
-        val.i =  *reinterpret_cast<jint*>(GetParamAddress());
-        break;
-      case Primitive::kPrimVoid:
-        LOG(FATAL) << "UNREACHABLE";
-        val.j = 0;
-        break;
-    }
-    args_.push_back(val);
-  }
-
- private:
-  ScopedObjectAccessUnchecked& soa_;
-  std::vector<jvalue>& args_;
-
-  DISALLOW_COPY_AND_ASSIGN(BuildPortableArgumentVisitor);
-};
-
-// Visits arguments on the stack placing them into the args vector, Object* arguments are converted
-// to jobjects.
 class BuildQuickArgumentVisitor : public QuickArgumentVisitor {
  public:
   BuildQuickArgumentVisitor(MethodHelper& caller_mh, mirror::AbstractMethod** sp,
@@ -126,46 +82,6 @@
 // which is responsible for recording callee save registers. We explicitly place into jobjects the
 // incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
 // field within the proxy object, which will box the primitive arguments and deal with error cases.
-extern "C" uint64_t artPortableProxyInvokeHandler(mirror::AbstractMethod* proxy_method,
-                                                 mirror::Object* receiver,
-                                                Thread* self, mirror::AbstractMethod** sp)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
-  const char* old_cause =
-      self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
-  self->VerifyStack();
-  // Start new JNI local reference state.
-  JNIEnvExt* env = self->GetJniEnv();
-  ScopedObjectAccessUnchecked soa(env);
-  ScopedJniEnvLocalRefState env_state(env);
-  // Create local ref. copies of proxy method and the receiver.
-  jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
-
-  // Placing arguments into args vector and remove the receiver.
-  MethodHelper proxy_mh(proxy_method);
-  std::vector<jvalue> args;
-  BuildPortableArgumentVisitor local_ref_visitor(proxy_mh, sp, soa, args);
-  local_ref_visitor.VisitArguments();
-  args.erase(args.begin());
-
-  // Convert proxy method into expected interface method.
-  mirror::AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
-  DCHECK(interface_method != NULL);
-  DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
-  jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
-
-  // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
-  // that performs allocations.
-  self->EndAssertNoThreadSuspension(old_cause);
-  JValue result = InvokeProxyInvocationHandler(soa, proxy_mh.GetShorty(),
-                                               rcvr_jobj, interface_method_jobj, args);
-  return result.GetJ();
-}
-
-// 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 place into jobjects the
-// incoming reference arguments (so they survive GC). We invoke the invocation handler, which is a
-// field within the proxy object, which will box the primitive arguments and deal with error cases.
 extern "C" uint64_t artQuickProxyInvokeHandler(mirror::AbstractMethod* proxy_method,
                                           mirror::Object* receiver,
                                           Thread* self, mirror::AbstractMethod** sp)
diff --git a/runtime/entrypoints/quick/quick_stub_entrypoints.cc b/runtime/entrypoints/quick/quick_stub_entrypoints.cc
index f2af6d2..d78bbf3 100644
--- a/runtime/entrypoints/quick/quick_stub_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_stub_entrypoints.cc
@@ -30,127 +30,6 @@
 
 namespace art {
 
-// Lazily resolve a method for portable. Called by stub code.
-extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
-                                                       mirror::Object* receiver,
-                                                       mirror::AbstractMethod** called_addr,
-                                                       Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  uint32_t dex_pc;
-  mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
-
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  InvokeType invoke_type;
-  bool is_range;
-  if (called->IsRuntimeMethod()) {
-    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();
-    switch (instr_code) {
-      case Instruction::INVOKE_DIRECT:
-        invoke_type = kDirect;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_DIRECT_RANGE:
-        invoke_type = kDirect;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_STATIC:
-        invoke_type = kStatic;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_STATIC_RANGE:
-        invoke_type = kStatic;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_SUPER:
-        invoke_type = kSuper;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_SUPER_RANGE:
-        invoke_type = kSuper;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_VIRTUAL:
-        invoke_type = kVirtual;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_VIRTUAL_RANGE:
-        invoke_type = kVirtual;
-        is_range = true;
-        break;
-      case Instruction::INVOKE_INTERFACE:
-        invoke_type = kInterface;
-        is_range = false;
-        break;
-      case Instruction::INVOKE_INTERFACE_RANGE:
-        invoke_type = kInterface;
-        is_range = true;
-        break;
-      default:
-        LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
-        // Avoid used uninitialized warnings.
-        invoke_type = kDirect;
-        is_range = true;
-    }
-    uint32_t dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
-    called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
-    // Refine called method based on receiver.
-    if (invoke_type == kVirtual) {
-      called = receiver->GetClass()->FindVirtualMethodForVirtual(called);
-    } else if (invoke_type == kInterface) {
-      called = receiver->GetClass()->FindVirtualMethodForInterface(called);
-    }
-  } else {
-    CHECK(called->IsStatic()) << PrettyMethod(called);
-    invoke_type = kStatic;
-  }
-  const void* code = NULL;
-  if (LIKELY(!thread->IsExceptionPending())) {
-    // Incompatible class change should have been handled in resolve method.
-    CHECK(!called->CheckIncompatibleClassChange(invoke_type));
-    // Ensure that the called method's class is initialized.
-    mirror::Class* called_class = called->GetDeclaringClass();
-    linker->EnsureInitialized(called_class, true, true);
-    if (LIKELY(called_class->IsInitialized())) {
-      code = called->GetEntryPointFromCompiledCode();
-      // TODO: remove this after we solve the link issue.
-      {  // for lazy link.
-        if (code == NULL) {
-          code = linker->GetOatCodeFor(called);
-        }
-      }
-    } else if (called_class->IsInitializing()) {
-      if (invoke_type == kStatic) {
-        // 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->GetEntryPointFromCompiledCode();
-        // TODO: remove this after we solve the link issue.
-        {  // for lazy link.
-          if (code == NULL) {
-            code = linker->GetOatCodeFor(called);
-          }
-        }
-      }
-    } else {
-      DCHECK(called_class->IsErroneous());
-    }
-  }
-  if (LIKELY(code != NULL)) {
-    // Expect class to at least be initializing.
-    DCHECK(called->GetDeclaringClass()->IsInitializing());
-    // Don't want infinite recursion.
-    DCHECK(code != GetResolutionTrampoline(linker));
-    // Set up entry into main method
-    *called_addr = called;
-  }
-  return code;
-}
-
 // Lazily resolve a method for quick. Called by stub code.
 extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
                                                     mirror::Object* receiver,
@@ -413,26 +292,4 @@
   self->QuickDeliverException();
 }
 
-// Used by the JNI dlsym stub to find the native method to invoke if none is registered.
-extern "C" void* artFindNativeMethod(Thread* self) {
-  Locks::mutator_lock_->AssertNotHeld(self);  // We come here as Native.
-  DCHECK(Thread::Current() == self);
-  ScopedObjectAccess soa(self);
-
-  mirror::AbstractMethod* method = self->GetCurrentMethod(NULL);
-  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 = soa.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;
-  }
-}
-
 }  // namespace art
diff --git a/runtime/entrypoints/quick/quick_thread_entrypoints.cc b/runtime/entrypoints/quick/quick_thread_entrypoints.cc
index e711714..b4d6c0b 100644
--- a/runtime/entrypoints/quick/quick_thread_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_thread_entrypoints.cc
@@ -15,7 +15,7 @@
  */
 
 #include "callee_save_frame.h"
-#include "runtime_support.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "thread.h"
 #include "thread_list.h"
 
diff --git a/runtime/entrypoints/quick/quick_throw_entrypoints.cc b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
index 9588698..3bfa2f2 100644
--- a/runtime/entrypoints/quick/quick_throw_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_throw_entrypoints.cc
@@ -15,9 +15,9 @@
  */
 
 #include "callee_save_frame.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "mirror/object.h"
 #include "object_utils.h"
-#include "runtime_support.h"
 #include "thread.h"
 #include "well_known_classes.h"
 
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 37c45fa..ef4b95c 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -24,6 +24,7 @@
 #include "dex_file-inl.h"
 #include "dex_instruction-inl.h"
 #include "dex_instruction.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "gc/accounting/card_table-inl.h"
 #include "invoke_arg_array_builder.h"
 #include "nth_caller_visitor.h"
@@ -35,7 +36,6 @@
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "object_utils.h"
-#include "runtime_support.h"
 #include "ScopedLocalRef.h"
 #include "scoped_thread_state_change.h"
 #include "thread.h"
diff --git a/runtime/mirror/abstract_method-inl.h b/runtime/mirror/abstract_method-inl.h
index 2df1367..d235e3e 100644
--- a/runtime/mirror/abstract_method-inl.h
+++ b/runtime/mirror/abstract_method-inl.h
@@ -20,9 +20,9 @@
 #include "abstract_method.h"
 
 #include "dex_file.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "object_array.h"
 #include "runtime.h"
-#include "runtime_support.h"
 
 namespace art {
 namespace mirror {
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 53a1df9..540ff9f 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -26,6 +26,7 @@
 #include "class_linker-inl.h"
 #include "common_test.h"
 #include "dex_file.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "field-inl.h"
 #include "gc/accounting/card_table-inl.h"
 #include "gc/heap.h"
@@ -33,7 +34,6 @@
 #include "abstract_method-inl.h"
 #include "object-inl.h"
 #include "object_array-inl.h"
-#include "runtime_support.h"
 #include "sirt_ref.h"
 #include "UniquePtr.h"
 
diff --git a/runtime/runtime_support_llvm.cc b/runtime/runtime_support_llvm.cc
deleted file mode 100644
index 93396d6..0000000
--- a/runtime/runtime_support_llvm.cc
+++ /dev/null
@@ -1,930 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "runtime_support_llvm.h"
-
-#include "ScopedLocalRef.h"
-#include "asm_support.h"
-#include "class_linker.h"
-#include "class_linker-inl.h"
-#include "dex_file-inl.h"
-#include "dex_instruction.h"
-#include "mirror/abstract_method-inl.h"
-#include "mirror/class-inl.h"
-#include "mirror/dex_cache-inl.h"
-#include "mirror/field-inl.h"
-#include "mirror/object.h"
-#include "mirror/object-inl.h"
-#include "mirror/object_array-inl.h"
-#include "nth_caller_visitor.h"
-#include "object_utils.h"
-#include "reflection.h"
-#include "runtime_support.h"
-#include "scoped_thread_state_change.h"
-#include "thread.h"
-#include "thread_list.h"
-#include "verifier/dex_gc_map.h"
-#include "verifier/method_verifier.h"
-#include "well_known_classes.h"
-
-#include <algorithm>
-#include <math.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-namespace art {
-
-using ::art::mirror::AbstractMethod;
-
-class ShadowFrameCopyVisitor : public StackVisitor {
- public:
-  explicit ShadowFrameCopyVisitor(Thread* self) : StackVisitor(self, NULL), prev_frame_(NULL),
-      top_frame_(NULL) {}
-
-  bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    if (IsShadowFrame()) {
-      ShadowFrame* cur_frame = GetCurrentShadowFrame();
-      size_t num_regs = cur_frame->NumberOfVRegs();
-      AbstractMethod* method = cur_frame->GetMethod();
-      uint32_t dex_pc = cur_frame->GetDexPC();
-      ShadowFrame* new_frame = ShadowFrame::Create(num_regs, NULL, method, dex_pc);
-
-      const uint8_t* gc_map = method->GetNativeGcMap();
-      uint32_t gc_map_length = static_cast<uint32_t>((gc_map[0] << 24) |
-                                                     (gc_map[1] << 16) |
-                                                     (gc_map[2] << 8) |
-                                                     (gc_map[3] << 0));
-      verifier::DexPcToReferenceMap dex_gc_map(gc_map + 4, gc_map_length);
-      const uint8_t* reg_bitmap = dex_gc_map.FindBitMap(dex_pc);
-      for (size_t reg = 0; reg < num_regs; ++reg) {
-        if (TestBitmap(reg, reg_bitmap)) {
-          new_frame->SetVRegReference(reg, cur_frame->GetVRegReference(reg));
-        } else {
-          new_frame->SetVReg(reg, cur_frame->GetVReg(reg));
-        }
-      }
-
-      if (prev_frame_ != NULL) {
-        prev_frame_->SetLink(new_frame);
-      } else {
-        top_frame_ = new_frame;
-      }
-      prev_frame_ = new_frame;
-    }
-    return true;
-  }
-
-  ShadowFrame* GetShadowFrameCopy() {
-    return top_frame_;
-  }
-
- private:
-  static bool TestBitmap(int reg, const uint8_t* reg_vector) {
-    return ((reg_vector[reg / 8] >> (reg % 8)) & 0x01) != 0;
-  }
-
-  ShadowFrame* prev_frame_;
-  ShadowFrame* top_frame_;
-};
-
-}  // namespace art
-
-extern "C" {
-using ::art::CatchHandlerIterator;
-using ::art::DexFile;
-using ::art::FindFieldFast;
-using ::art::FindMethodFast;
-using ::art::InstanceObjectRead;
-using ::art::InstanceObjectWrite;
-using ::art::InstancePrimitiveRead;
-using ::art::InstancePrimitiveWrite;
-using ::art::Instruction;
-using ::art::InvokeType;
-using ::art::JNIEnvExt;
-using ::art::JValue;
-using ::art::Locks;
-using ::art::MethodHelper;
-using ::art::PrettyClass;
-using ::art::PrettyMethod;
-using ::art::Primitive;
-using ::art::ResolveStringFromCode;
-using ::art::Runtime;
-using ::art::ScopedJniEnvLocalRefState;
-using ::art::ScopedObjectAccessUnchecked;
-using ::art::ShadowFrame;
-using ::art::ShadowFrameCopyVisitor;
-using ::art::StaticObjectRead;
-using ::art::StaticObjectWrite;
-using ::art::StaticPrimitiveRead;
-using ::art::StaticPrimitiveWrite;
-using ::art::Thread;
-using ::art::Thread;
-using ::art::ThrowArithmeticExceptionDivideByZero;
-using ::art::ThrowArrayIndexOutOfBoundsException;
-using ::art::ThrowArrayStoreException;
-using ::art::ThrowClassCastException;
-using ::art::ThrowLocation;
-using ::art::ThrowNoSuchMethodError;
-using ::art::ThrowNullPointerException;
-using ::art::ThrowNullPointerExceptionFromDexPC;
-using ::art::ThrowStackOverflowError;
-using ::art::kDirect;
-using ::art::kInterface;
-using ::art::kNative;
-using ::art::kStatic;
-using ::art::kSuper;
-using ::art::kVirtual;
-using ::art::mirror::AbstractMethod;
-using ::art::mirror::Array;
-using ::art::mirror::Class;
-using ::art::mirror::Field;
-using ::art::mirror::Object;
-using ::art::mirror::Throwable;
-
-//----------------------------------------------------------------------------
-// Thread
-//----------------------------------------------------------------------------
-
-Thread* art_portable_get_current_thread_from_code() {
-#if defined(__arm__) || defined(__i386__)
-  LOG(FATAL) << "UNREACHABLE";
-#endif
-  return Thread::Current();
-}
-
-void* art_portable_set_current_thread_from_code(void* thread_object_addr) {
-  // Hijacked to set r9 on ARM.
-  LOG(FATAL) << "UNREACHABLE";
-  return NULL;
-}
-
-void art_portable_lock_object_from_code(Object* obj, Thread* thread)
-    EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) {
-  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 art_portable_unlock_object_from_code(Object* obj, Thread* thread)
-    UNLOCK_FUNCTION(monitor_lock_) {
-  DCHECK(obj != NULL);  // Assumed to have been checked before entry
-  // MonitorExit may throw exception
-  obj->MonitorExit(thread);
-}
-
-void art_portable_test_suspend_from_code(Thread* self)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  CheckSuspend(self);
-  if (Runtime::Current()->GetInstrumentation()->ShouldPortableCodeDeoptimize()) {
-    // Save out the shadow frame to the heap
-    ShadowFrameCopyVisitor visitor(self);
-    visitor.WalkStack(true);
-    self->SetDeoptimizationShadowFrame(visitor.GetShadowFrameCopy());
-    self->SetDeoptimizationReturnValue(JValue());
-    self->SetException(ThrowLocation(), reinterpret_cast<Throwable*>(-1));
-  }
-}
-
-ShadowFrame* art_portable_push_shadow_frame_from_code(Thread* thread,
-                                                      ShadowFrame* new_shadow_frame,
-                                                      AbstractMethod* method,
-                                                      uint32_t num_vregs) {
-  ShadowFrame* old_frame = thread->PushShadowFrame(new_shadow_frame);
-  new_shadow_frame->SetMethod(method);
-  new_shadow_frame->SetNumberOfVRegs(num_vregs);
-  return old_frame;
-}
-
-void art_portable_pop_shadow_frame_from_code(void*) {
-  LOG(FATAL) << "Implemented by IRBuilder.";
-}
-
-void art_portable_mark_gc_card_from_code(void *, void*) {
-  LOG(FATAL) << "Implemented by IRBuilder.";
-}
-
-//----------------------------------------------------------------------------
-// Exception
-//----------------------------------------------------------------------------
-
-bool art_portable_is_exception_pending_from_code() {
-  LOG(FATAL) << "Implemented by IRBuilder.";
-  return false;
-}
-
-void art_portable_throw_div_zero_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ThrowArithmeticExceptionDivideByZero();
-}
-
-void art_portable_throw_array_bounds_from_code(int32_t index, int32_t length)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ThrowArrayIndexOutOfBoundsException(index, length);
-}
-
-void art_portable_throw_no_such_method_from_code(int32_t method_idx)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ThrowNoSuchMethodError(method_idx);
-}
-
-void art_portable_throw_null_pointer_exception_from_code(uint32_t dex_pc)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  // TODO: remove dex_pc argument from caller.
-  UNUSED(dex_pc);
-  Thread* self = Thread::Current();
-  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
-  ThrowNullPointerExceptionFromDexPC(throw_location);
-}
-
-void art_portable_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ThrowStackOverflowError(Thread::Current());
-}
-
-void art_portable_throw_exception_from_code(Throwable* exception)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Thread* self = Thread::Current();
-  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
-  if (exception == NULL) {
-    ThrowNullPointerException(NULL, "throw with null exception");
-  } else {
-    self->SetException(throw_location, exception);
-  }
-}
-
-void* art_portable_get_and_clear_exception(Thread* self)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  DCHECK(self->IsExceptionPending());
-  // TODO: make this inline.
-  Throwable* exception = self->GetException(NULL);
-  self->ClearException();
-  return exception;
-}
-
-int32_t art_portable_find_catch_block_from_code(AbstractMethod* current_method,
-                                                uint32_t ti_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Thread* self = Thread::Current();  // TODO: make an argument.
-  ThrowLocation throw_location;
-  Throwable* exception = self->GetException(&throw_location);
-  // Check for special deoptimization exception.
-  if (UNLIKELY(reinterpret_cast<int32_t>(exception) == -1)) {
-    return -1;
-  }
-  Class* exception_type = exception->GetClass();
-  MethodHelper mh(current_method);
-  const DexFile::CodeItem* code_item = mh.GetCodeItem();
-  DCHECK_LT(ti_offset, code_item->tries_size_);
-  const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset);
-
-  int iter_index = 0;
-  int result = -1;
-  uint32_t catch_dex_pc = -1;
-  // Iterate over the catch handlers associated with dex_pc
-  for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) {
-    uint16_t iter_type_idx = it.GetHandlerTypeIndex();
-    // Catch all case
-    if (iter_type_idx == DexFile::kDexNoIndex16) {
-      catch_dex_pc = it.GetHandlerAddress();
-      result = iter_index;
-      break;
-    }
-    // Does this catch exception type apply?
-    Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
-    if (UNLIKELY(iter_exception_type == NULL)) {
-      // TODO: check, the verifier (class linker?) should take care of resolving all exception
-      //       classes early.
-      LOG(WARNING) << "Unresolved exception class when finding catch block: "
-          << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
-    } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
-      catch_dex_pc = it.GetHandlerAddress();
-      result = iter_index;
-      break;
-    }
-    ++iter_index;
-  }
-  if (result != -1) {
-    // Handler found.
-    Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent(self,
-                                                                   throw_location,
-                                                                   current_method,
-                                                                   catch_dex_pc,
-                                                                   exception);
-    // If the catch block has no move-exception then clear the exception for it.
-    const Instruction* first_catch_instr =
-        Instruction::At(&mh.GetCodeItem()->insns_[catch_dex_pc]);
-    if (first_catch_instr->Opcode() != Instruction::MOVE_EXCEPTION) {
-      self->ClearException();
-    }
-  }
-  return result;
-}
-
-
-//----------------------------------------------------------------------------
-// Object Space
-//----------------------------------------------------------------------------
-
-Object* art_portable_alloc_object_from_code(uint32_t type_idx, AbstractMethod* referrer, Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return AllocObjectFromCode(type_idx, referrer, thread, false);
-}
-
-Object* art_portable_alloc_object_from_code_with_access_check(uint32_t type_idx,
-                                                              AbstractMethod* referrer,
-                                                              Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return AllocObjectFromCode(type_idx, referrer, thread, true);
-}
-
-Object* art_portable_alloc_array_from_code(uint32_t type_idx,
-                                           AbstractMethod* referrer,
-                                           uint32_t length,
-                                           Thread* self)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return AllocArrayFromCode(type_idx, referrer, length, self, false);
-}
-
-Object* art_portable_alloc_array_from_code_with_access_check(uint32_t type_idx,
-                                                             AbstractMethod* referrer,
-                                                             uint32_t length,
-                                                             Thread* self)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return AllocArrayFromCode(type_idx, referrer, length, self, true);
-}
-
-Object* art_portable_check_and_alloc_array_from_code(uint32_t type_idx,
-                                                     AbstractMethod* referrer,
-                                                     uint32_t length,
-                                                     Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, false);
-}
-
-Object* art_portable_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
-                                                                       AbstractMethod* referrer,
-                                                                       uint32_t length,
-                                                                       Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return CheckAndAllocArrayFromCode(type_idx, referrer, length, thread, true);
-}
-
-static AbstractMethod* FindMethodHelper(uint32_t method_idx,
-                                        Object* this_object,
-                                        AbstractMethod* caller_method,
-                                        bool access_check,
-                                        InvokeType type,
-                                        Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  AbstractMethod* method = FindMethodFast(method_idx,
-                                          this_object,
-                                          caller_method,
-                                          access_check,
-                                          type);
-  if (UNLIKELY(method == NULL)) {
-    method = FindMethodFromCode(method_idx, this_object, caller_method,
-                                thread, access_check, type);
-    if (UNLIKELY(method == NULL)) {
-      CHECK(thread->IsExceptionPending());
-      return 0;  // failure
-    }
-  }
-  DCHECK(!thread->IsExceptionPending());
-  const void* code = method->GetEntryPointFromCompiledCode();
-
-  // When we return, the caller will branch to this address, so it had better not be 0!
-  if (UNLIKELY(code == NULL)) {
-      MethodHelper mh(method);
-      LOG(FATAL) << "Code was NULL in method: " << PrettyMethod(method)
-                 << " location: " << mh.GetDexFile().GetLocation();
-  }
-  return method;
-}
-
-Object* art_portable_find_static_method_from_code_with_access_check(uint32_t method_idx,
-                                                                    Object* this_object,
-                                                                    AbstractMethod* referrer,
-                                                                    Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, true, kStatic, thread);
-}
-
-Object* art_portable_find_direct_method_from_code_with_access_check(uint32_t method_idx,
-                                                                    Object* this_object,
-                                                                    AbstractMethod* referrer,
-                                                                    Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, true, kDirect, thread);
-}
-
-Object* art_portable_find_virtual_method_from_code_with_access_check(uint32_t method_idx,
-                                                                     Object* this_object,
-                                                                     AbstractMethod* referrer,
-                                                                     Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, true, kVirtual, thread);
-}
-
-Object* art_portable_find_super_method_from_code_with_access_check(uint32_t method_idx,
-                                                                   Object* this_object,
-                                                                   AbstractMethod* referrer,
-                                                                   Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, true, kSuper, thread);
-}
-
-Object* art_portable_find_interface_method_from_code_with_access_check(uint32_t method_idx,
-                                                                       Object* this_object,
-                                                                       AbstractMethod* referrer,
-                                                                       Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, true, kInterface, thread);
-}
-
-Object* art_portable_find_interface_method_from_code(uint32_t method_idx,
-                                                     Object* this_object,
-                                                     AbstractMethod* referrer,
-                                                     Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return FindMethodHelper(method_idx, this_object, referrer, false, kInterface, thread);
-}
-
-Object* art_portable_initialize_static_storage_from_code(uint32_t type_idx,
-                                                         AbstractMethod* referrer,
-                                                         Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return ResolveVerifyAndClinit(type_idx, referrer, thread, true, false);
-}
-
-Object* art_portable_initialize_type_from_code(uint32_t type_idx,
-                                               AbstractMethod* referrer,
-                                               Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return ResolveVerifyAndClinit(type_idx, referrer, thread, false, false);
-}
-
-Object* art_portable_initialize_type_and_verify_access_from_code(uint32_t type_idx,
-                                                                 AbstractMethod* referrer,
-                                                                 Thread* thread)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  // Called when caller isn't guaranteed to have access to a type and the dex cache may be
-  // unpopulated
-  return ResolveVerifyAndClinit(type_idx, referrer, thread, false, true);
-}
-
-Object* art_portable_resolve_string_from_code(AbstractMethod* referrer, uint32_t string_idx)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  return ResolveStringFromCode(referrer, string_idx);
-}
-
-int32_t art_portable_set32_static_from_code(uint32_t field_idx,
-                                            AbstractMethod* referrer,
-                                            int32_t new_value)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx,
-                               referrer,
-                               StaticPrimitiveWrite,
-                               sizeof(uint32_t));
-  if (LIKELY(field != NULL)) {
-    field->Set32(field->GetDeclaringClass(), new_value);
-    return 0;
-  }
-  field = FindFieldFromCode(field_idx,
-                            referrer,
-                            Thread::Current(),
-                            StaticPrimitiveWrite,
-                            sizeof(uint32_t),
-                            true);
-  if (LIKELY(field != NULL)) {
-    field->Set32(field->GetDeclaringClass(), new_value);
-    return 0;
-  }
-  return -1;
-}
-
-int32_t art_portable_set64_static_from_code(uint32_t field_idx,
-                                            AbstractMethod* referrer,
-                                            int64_t new_value)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(uint64_t));
-  if (LIKELY(field != NULL)) {
-    field->Set64(field->GetDeclaringClass(), new_value);
-    return 0;
-  }
-  field = FindFieldFromCode(field_idx,
-                            referrer,
-                            Thread::Current(),
-                            StaticPrimitiveWrite,
-                            sizeof(uint64_t),
-                            true);
-  if (LIKELY(field != NULL)) {
-    field->Set64(field->GetDeclaringClass(), new_value);
-    return 0;
-  }
-  return -1;
-}
-
-int32_t art_portable_set_obj_static_from_code(uint32_t field_idx,
-                                              AbstractMethod* referrer,
-                                              Object* new_value)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, StaticObjectWrite, sizeof(Object*));
-  if (LIKELY(field != NULL)) {
-    field->SetObj(field->GetDeclaringClass(), new_value);
-    return 0;
-  }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            StaticObjectWrite, sizeof(Object*), true);
-  if (LIKELY(field != NULL)) {
-    field->SetObj(field->GetDeclaringClass(), new_value);
-    return 0;
-  }
-  return -1;
-}
-
-int32_t art_portable_get32_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint32_t));
-  if (LIKELY(field != NULL)) {
-    return field->Get32(field->GetDeclaringClass());
-  }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            StaticPrimitiveRead, sizeof(uint32_t), true);
-  if (LIKELY(field != NULL)) {
-    return field->Get32(field->GetDeclaringClass());
-  }
-  return 0;
-}
-
-int64_t art_portable_get64_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(uint64_t));
-  if (LIKELY(field != NULL)) {
-    return field->Get64(field->GetDeclaringClass());
-  }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            StaticPrimitiveRead, sizeof(uint64_t), true);
-  if (LIKELY(field != NULL)) {
-    return field->Get64(field->GetDeclaringClass());
-  }
-  return 0;
-}
-
-Object* art_portable_get_obj_static_from_code(uint32_t field_idx, AbstractMethod* referrer)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, StaticObjectRead, sizeof(Object*));
-  if (LIKELY(field != NULL)) {
-    return field->GetObj(field->GetDeclaringClass());
-  }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            StaticObjectRead, sizeof(Object*), true);
-  if (LIKELY(field != NULL)) {
-    return field->GetObj(field->GetDeclaringClass());
-  }
-  return 0;
-}
-
-int32_t art_portable_set32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
-                                              Object* obj, uint32_t new_value)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint32_t));
-  if (LIKELY(field != NULL)) {
-    field->Set32(obj, new_value);
-    return 0;
-  }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstancePrimitiveWrite, sizeof(uint32_t), true);
-  if (LIKELY(field != NULL)) {
-    field->Set32(obj, new_value);
-    return 0;
-  }
-  return -1;
-}
-
-int32_t art_portable_set64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
-                                              Object* obj, int64_t new_value)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(uint64_t));
-  if (LIKELY(field != NULL)) {
-    field->Set64(obj, new_value);
-    return 0;
-  }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstancePrimitiveWrite, sizeof(uint64_t), true);
-  if (LIKELY(field != NULL)) {
-    field->Set64(obj, new_value);
-    return 0;
-  }
-  return -1;
-}
-
-int32_t art_portable_set_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer,
-                                                Object* obj, Object* new_value)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, InstanceObjectWrite, sizeof(Object*));
-  if (LIKELY(field != NULL)) {
-    field->SetObj(obj, new_value);
-    return 0;
-  }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstanceObjectWrite, sizeof(Object*), true);
-  if (LIKELY(field != NULL)) {
-    field->SetObj(obj, new_value);
-    return 0;
-  }
-  return -1;
-}
-
-int32_t art_portable_get32_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint32_t));
-  if (LIKELY(field != NULL)) {
-    return field->Get32(obj);
-  }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstancePrimitiveRead, sizeof(uint32_t), true);
-  if (LIKELY(field != NULL)) {
-    return field->Get32(obj);
-  }
-  return 0;
-}
-
-int64_t art_portable_get64_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(uint64_t));
-  if (LIKELY(field != NULL)) {
-    return field->Get64(obj);
-  }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstancePrimitiveRead, sizeof(uint64_t), true);
-  if (LIKELY(field != NULL)) {
-    return field->Get64(obj);
-  }
-  return 0;
-}
-
-Object* art_portable_get_obj_instance_from_code(uint32_t field_idx, AbstractMethod* referrer, Object* obj)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Field* field = FindFieldFast(field_idx, referrer, InstanceObjectRead, sizeof(Object*));
-  if (LIKELY(field != NULL)) {
-    return field->GetObj(obj);
-  }
-  field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
-                            InstanceObjectRead, sizeof(Object*), true);
-  if (LIKELY(field != NULL)) {
-    return field->GetObj(obj);
-  }
-  return 0;
-}
-
-void art_portable_fill_array_data_from_code(AbstractMethod* method, uint32_t dex_pc,
-                                            Array* array, uint32_t payload_offset)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  // Test: Is array equal to null? (Guard NullPointerException)
-  if (UNLIKELY(array == NULL)) {
-    art_portable_throw_null_pointer_exception_from_code(dex_pc);
-    return;
-  }
-
-  // Find the payload from the CodeItem
-  MethodHelper mh(method);
-  const DexFile::CodeItem* code_item = mh.GetCodeItem();
-
-  DCHECK_GT(code_item->insns_size_in_code_units_, payload_offset);
-
-  const Instruction::ArrayDataPayload* payload =
-    reinterpret_cast<const Instruction::ArrayDataPayload*>(
-        code_item->insns_ + payload_offset);
-
-  DCHECK_EQ(payload->ident,
-            static_cast<uint16_t>(Instruction::kArrayDataSignature));
-
-  // Test: Is array big enough?
-  uint32_t array_len = static_cast<uint32_t>(array->GetLength());
-  if (UNLIKELY(array_len < payload->element_count)) {
-    int32_t last_index = payload->element_count - 1;
-    art_portable_throw_array_bounds_from_code(array_len, last_index);
-    return;
-  }
-
-  // Copy the data
-  size_t size = payload->element_width * payload->element_count;
-  memcpy(array->GetRawData(payload->element_width), payload->data, size);
-}
-
-
-
-//----------------------------------------------------------------------------
-// Type checking, in the nature of casting
-//----------------------------------------------------------------------------
-
-int32_t art_portable_is_assignable_from_code(const Class* dest_type, const Class* src_type)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  DCHECK(dest_type != NULL);
-  DCHECK(src_type != NULL);
-  return dest_type->IsAssignableFrom(src_type) ? 1 : 0;
-}
-
-void art_portable_check_cast_from_code(const Class* dest_type, const Class* src_type)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
-  DCHECK(src_type->IsClass()) << PrettyClass(src_type);
-  if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
-    ThrowClassCastException(dest_type, src_type);
-  }
-}
-
-void art_portable_check_put_array_element_from_code(const Object* element,
-                                                    const Object* array)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  if (element == NULL) {
-    return;
-  }
-  DCHECK(array != NULL);
-  Class* array_class = array->GetClass();
-  DCHECK(array_class != NULL);
-  Class* component_type = array_class->GetComponentType();
-  Class* element_class = element->GetClass();
-  if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
-    ThrowArrayStoreException(element_class, array_class);
-  }
-  return;
-}
-
-//----------------------------------------------------------------------------
-// JNI
-//----------------------------------------------------------------------------
-
-// Called on entry to JNI, transition out of Runnable and release share of mutator_lock_.
-uint32_t art_portable_jni_method_start(Thread* self)
-    UNLOCK_FUNCTION(GlobalSynchronizatio::mutator_lock_) {
-  JNIEnvExt* env = self->GetJniEnv();
-  uint32_t saved_local_ref_cookie = env->local_ref_cookie;
-  env->local_ref_cookie = env->locals.GetSegmentState();
-  self->TransitionFromRunnableToSuspended(kNative);
-  return saved_local_ref_cookie;
-}
-
-uint32_t art_portable_jni_method_start_synchronized(jobject to_lock, Thread* self)
-    UNLOCK_FUNCTION(Locks::mutator_lock_) {
-  self->DecodeJObject(to_lock)->MonitorEnter(self);
-  return art_portable_jni_method_start(self);
-}
-
-static inline void PopLocalReferences(uint32_t saved_local_ref_cookie, Thread* self) {
-  JNIEnvExt* env = self->GetJniEnv();
-  env->locals.SetSegmentState(env->local_ref_cookie);
-  env->local_ref_cookie = saved_local_ref_cookie;
-}
-
-void art_portable_jni_method_end(uint32_t saved_local_ref_cookie, Thread* self)
-    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
-  self->TransitionFromSuspendedToRunnable();
-  PopLocalReferences(saved_local_ref_cookie, self);
-}
-
-
-void art_portable_jni_method_end_synchronized(uint32_t saved_local_ref_cookie,
-                                              jobject locked,
-                                              Thread* self)
-    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
-  self->TransitionFromSuspendedToRunnable();
-  UnlockJniSynchronizedMethod(locked, self);  // Must decode before pop.
-  PopLocalReferences(saved_local_ref_cookie, self);
-}
-
-Object* art_portable_jni_method_end_with_reference(jobject result,
-                                                   uint32_t saved_local_ref_cookie,
-                                                   Thread* self)
-    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
-  self->TransitionFromSuspendedToRunnable();
-  Object* o = self->DecodeJObject(result);  // Must decode before pop.
-  PopLocalReferences(saved_local_ref_cookie, self);
-  // Process result.
-  if (UNLIKELY(self->GetJniEnv()->check_jni)) {
-    if (self->IsExceptionPending()) {
-      return NULL;
-    }
-    CheckReferenceResult(o, self);
-  }
-  return o;
-}
-
-Object* art_portable_jni_method_end_with_reference_synchronized(jobject result,
-                                                                uint32_t saved_local_ref_cookie,
-                                                                jobject locked,
-                                                                Thread* self)
-    SHARED_LOCK_FUNCTION(Locks::mutator_lock_) {
-  self->TransitionFromSuspendedToRunnable();
-  UnlockJniSynchronizedMethod(locked, self);  // Must decode before pop.
-  Object* o = self->DecodeJObject(result);
-  PopLocalReferences(saved_local_ref_cookie, self);
-  // Process result.
-  if (UNLIKELY(self->GetJniEnv()->check_jni)) {
-    if (self->IsExceptionPending()) {
-      return NULL;
-    }
-    CheckReferenceResult(o, self);
-  }
-  return o;
-}
-
-// Handler for invocation on proxy methods. Create a boxed argument array and invoke the invocation
-// handler which is a field within the proxy object receiver. The var args encode the arguments
-// with the last argument being a pointer to a JValue to store the result in.
-void art_portable_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  va_list ap;
-  va_start(ap, proxy_method);
-
-  Object* receiver = va_arg(ap, Object*);
-  Thread* self = va_arg(ap, Thread*);
-  MethodHelper proxy_mh(proxy_method);
-
-  // Ensure we don't get thread suspension until the object arguments are safely in jobjects.
-  const char* old_cause =
-      self->StartAssertNoThreadSuspension("Adding to IRT proxy object arguments");
-  self->VerifyStack();
-
-  // Start new JNI local reference state.
-  JNIEnvExt* env = self->GetJniEnv();
-  ScopedObjectAccessUnchecked soa(env);
-  ScopedJniEnvLocalRefState env_state(env);
-
-  // Create local ref. copies of the receiver.
-  jobject rcvr_jobj = soa.AddLocalReference<jobject>(receiver);
-
-  // Convert proxy method into expected interface method.
-  AbstractMethod* interface_method = proxy_method->FindOverriddenMethod();
-  DCHECK(interface_method != NULL);
-  DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
-  jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
-
-  // Record arguments and turn Object* arguments into jobject to survive GC.
-  std::vector<jvalue> args;
-  const size_t num_params = proxy_mh.NumArgs();
-  for (size_t i = 1; i < num_params; ++i) {
-    jvalue val;
-    switch (proxy_mh.GetParamPrimitiveType(i)) {
-      case Primitive::kPrimNot:
-        val.l = soa.AddLocalReference<jobject>(va_arg(ap, Object*));
-        break;
-      case Primitive::kPrimBoolean:  // Fall-through.
-      case Primitive::kPrimByte:     // Fall-through.
-      case Primitive::kPrimChar:     // Fall-through.
-      case Primitive::kPrimShort:    // Fall-through.
-      case Primitive::kPrimInt:      // Fall-through.
-        val.i = va_arg(ap, jint);
-        break;
-      case Primitive::kPrimFloat:
-        // TODO: should this be jdouble? Floats aren't passed to var arg routines.
-        val.i = va_arg(ap, jint);
-        break;
-      case Primitive::kPrimDouble:
-        val.d = (va_arg(ap, jdouble));
-        break;
-      case Primitive::kPrimLong:
-        val.j = (va_arg(ap, jlong));
-        break;
-      case Primitive::kPrimVoid:
-        LOG(FATAL) << "UNREACHABLE";
-        val.j = 0;
-        break;
-    }
-    args.push_back(val);
-  }
-  self->EndAssertNoThreadSuspension(old_cause);
-  JValue* result_location = NULL;
-  const char* shorty = proxy_mh.GetShorty();
-  if (shorty[0] != 'V') {
-    result_location = va_arg(ap, JValue*);
-  }
-  va_end(ap);
-  JValue result = InvokeProxyInvocationHandler(soa, shorty, rcvr_jobj, interface_method_jobj, args);
-  if (result_location != NULL) {
-    *result_location = result;
-  }
-}
-
-//----------------------------------------------------------------------------
-// Memory barrier
-//----------------------------------------------------------------------------
-
-void art_portable_constructor_barrier() {
-  LOG(FATAL) << "Implemented by IRBuilder.";
-}
-}  // extern "C"
diff --git a/runtime/runtime_support_llvm.h b/runtime/runtime_support_llvm.h
deleted file mode 100644
index 43ea953..0000000
--- a/runtime/runtime_support_llvm.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_RUNTIME_SUPPORT_LLVM_H_
-#define ART_RUNTIME_RUNTIME_SUPPORT_LLVM_H_
-
-extern "C" {
-//----------------------------------------------------------------------------
-// Runtime Support Function Lookup Callback
-//----------------------------------------------------------------------------
-void* art_portable_find_runtime_support_func(void* context, const char* name);
-}  // extern "C"
-
-#endif  // ART_RUNTIME_RUNTIME_SUPPORT_LLVM_H_
diff --git a/runtime/thread.cc b/runtime/thread.cc
index d5fdd20..97a1410 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -38,6 +38,7 @@
 #include "cutils/atomic-inline.h"
 #include "debugger.h"
 #include "dex_file-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "gc_map.h"
 #include "gc/accounting/card_table-inl.h"
 #include "gc/heap.h"
@@ -54,7 +55,6 @@
 #include "object_utils.h"
 #include "reflection.h"
 #include "runtime.h"
-#include "runtime_support.h"
 #include "scoped_thread_state_change.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
@@ -86,16 +86,23 @@
 }
 #endif
 
+void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints);
+
 void Thread::InitFunctionPointers() {
 #if !defined(__APPLE__)  // The Mac GCC is too old to accept this code.
   // Insert a placeholder so we can easily tell if we call an unimplemented entry point.
-  uintptr_t* begin = reinterpret_cast<uintptr_t*>(&entrypoints_);
-  uintptr_t* end = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(begin) + sizeof(entrypoints_));
+  uintptr_t* begin = reinterpret_cast<uintptr_t*>(&quick_entrypoints_);
+  uintptr_t* end = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(begin) + sizeof(quick_entrypoints_));
+  for (uintptr_t* it = begin; it != end; ++it) {
+    *it = reinterpret_cast<uintptr_t>(UnimplementedEntryPoint);
+  }
+  begin = reinterpret_cast<uintptr_t*>(&portable_entrypoints_);
+  end = reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(begin) + sizeof(portable_entrypoints_));
   for (uintptr_t* it = begin; it != end; ++it) {
     *it = reinterpret_cast<uintptr_t>(UnimplementedEntryPoint);
   }
 #endif
-  InitEntryPoints(&entrypoints_);
+  InitEntryPoints(&quick_entrypoints_, &portable_entrypoints_);
 }
 
 void Thread::SetDeoptimizationShadowFrame(ShadowFrame* sf) {
@@ -1582,86 +1589,87 @@
   uint32_t offset;
   const char* name;
 };
-#define ENTRY_POINT_INFO(x) { ENTRYPOINT_OFFSET(x), #x }
+#define QUICK_ENTRY_POINT_INFO(x) { QUICK_ENTRYPOINT_OFFSET(x), #x }
+#define PORTABLE_ENTRY_POINT_INFO(x) { PORTABLE_ENTRYPOINT_OFFSET(x), #x }
 static const EntryPointInfo gThreadEntryPointInfo[] = {
-  ENTRY_POINT_INFO(pAllocArrayFromCode),
-  ENTRY_POINT_INFO(pAllocArrayFromCodeWithAccessCheck),
-  ENTRY_POINT_INFO(pAllocObjectFromCode),
-  ENTRY_POINT_INFO(pAllocObjectFromCodeWithAccessCheck),
-  ENTRY_POINT_INFO(pCheckAndAllocArrayFromCode),
-  ENTRY_POINT_INFO(pCheckAndAllocArrayFromCodeWithAccessCheck),
-  ENTRY_POINT_INFO(pInstanceofNonTrivialFromCode),
-  ENTRY_POINT_INFO(pCanPutArrayElementFromCode),
-  ENTRY_POINT_INFO(pCheckCastFromCode),
-  ENTRY_POINT_INFO(pInitializeStaticStorage),
-  ENTRY_POINT_INFO(pInitializeTypeAndVerifyAccessFromCode),
-  ENTRY_POINT_INFO(pInitializeTypeFromCode),
-  ENTRY_POINT_INFO(pResolveStringFromCode),
-  ENTRY_POINT_INFO(pSet32Instance),
-  ENTRY_POINT_INFO(pSet32Static),
-  ENTRY_POINT_INFO(pSet64Instance),
-  ENTRY_POINT_INFO(pSet64Static),
-  ENTRY_POINT_INFO(pSetObjInstance),
-  ENTRY_POINT_INFO(pSetObjStatic),
-  ENTRY_POINT_INFO(pGet32Instance),
-  ENTRY_POINT_INFO(pGet32Static),
-  ENTRY_POINT_INFO(pGet64Instance),
-  ENTRY_POINT_INFO(pGet64Static),
-  ENTRY_POINT_INFO(pGetObjInstance),
-  ENTRY_POINT_INFO(pGetObjStatic),
-  ENTRY_POINT_INFO(pHandleFillArrayDataFromCode),
-  ENTRY_POINT_INFO(pJniMethodStart),
-  ENTRY_POINT_INFO(pJniMethodStartSynchronized),
-  ENTRY_POINT_INFO(pJniMethodEnd),
-  ENTRY_POINT_INFO(pJniMethodEndSynchronized),
-  ENTRY_POINT_INFO(pJniMethodEndWithReference),
-  ENTRY_POINT_INFO(pJniMethodEndWithReferenceSynchronized),
-  ENTRY_POINT_INFO(pLockObjectFromCode),
-  ENTRY_POINT_INFO(pUnlockObjectFromCode),
-  ENTRY_POINT_INFO(pCmpgDouble),
-  ENTRY_POINT_INFO(pCmpgFloat),
-  ENTRY_POINT_INFO(pCmplDouble),
-  ENTRY_POINT_INFO(pCmplFloat),
-  ENTRY_POINT_INFO(pFmod),
-  ENTRY_POINT_INFO(pSqrt),
-  ENTRY_POINT_INFO(pL2d),
-  ENTRY_POINT_INFO(pFmodf),
-  ENTRY_POINT_INFO(pL2f),
-  ENTRY_POINT_INFO(pD2iz),
-  ENTRY_POINT_INFO(pF2iz),
-  ENTRY_POINT_INFO(pIdivmod),
-  ENTRY_POINT_INFO(pD2l),
-  ENTRY_POINT_INFO(pF2l),
-  ENTRY_POINT_INFO(pLdiv),
-  ENTRY_POINT_INFO(pLdivmod),
-  ENTRY_POINT_INFO(pLmul),
-  ENTRY_POINT_INFO(pShlLong),
-  ENTRY_POINT_INFO(pShrLong),
-  ENTRY_POINT_INFO(pUshrLong),
-  ENTRY_POINT_INFO(pInterpreterToInterpreterEntry),
-  ENTRY_POINT_INFO(pInterpreterToQuickEntry),
-  ENTRY_POINT_INFO(pIndexOf),
-  ENTRY_POINT_INFO(pMemcmp16),
-  ENTRY_POINT_INFO(pStringCompareTo),
-  ENTRY_POINT_INFO(pMemcpy),
-  ENTRY_POINT_INFO(pPortableResolutionTrampolineFromCode),
-  ENTRY_POINT_INFO(pQuickResolutionTrampolineFromCode),
-  ENTRY_POINT_INFO(pInvokeDirectTrampolineWithAccessCheck),
-  ENTRY_POINT_INFO(pInvokeInterfaceTrampoline),
-  ENTRY_POINT_INFO(pInvokeInterfaceTrampolineWithAccessCheck),
-  ENTRY_POINT_INFO(pInvokeStaticTrampolineWithAccessCheck),
-  ENTRY_POINT_INFO(pInvokeSuperTrampolineWithAccessCheck),
-  ENTRY_POINT_INFO(pInvokeVirtualTrampolineWithAccessCheck),
-  ENTRY_POINT_INFO(pCheckSuspendFromCode),
-  ENTRY_POINT_INFO(pTestSuspendFromCode),
-  ENTRY_POINT_INFO(pDeliverException),
-  ENTRY_POINT_INFO(pThrowArrayBoundsFromCode),
-  ENTRY_POINT_INFO(pThrowDivZeroFromCode),
-  ENTRY_POINT_INFO(pThrowNoSuchMethodFromCode),
-  ENTRY_POINT_INFO(pThrowNullPointerFromCode),
-  ENTRY_POINT_INFO(pThrowStackOverflowFromCode),
+  QUICK_ENTRY_POINT_INFO(pAllocArrayFromCode),
+  QUICK_ENTRY_POINT_INFO(pAllocArrayFromCodeWithAccessCheck),
+  QUICK_ENTRY_POINT_INFO(pAllocObjectFromCode),
+  QUICK_ENTRY_POINT_INFO(pAllocObjectFromCodeWithAccessCheck),
+  QUICK_ENTRY_POINT_INFO(pCheckAndAllocArrayFromCode),
+  QUICK_ENTRY_POINT_INFO(pCheckAndAllocArrayFromCodeWithAccessCheck),
+  QUICK_ENTRY_POINT_INFO(pInstanceofNonTrivialFromCode),
+  QUICK_ENTRY_POINT_INFO(pCanPutArrayElementFromCode),
+  QUICK_ENTRY_POINT_INFO(pCheckCastFromCode),
+  QUICK_ENTRY_POINT_INFO(pInitializeStaticStorage),
+  QUICK_ENTRY_POINT_INFO(pInitializeTypeAndVerifyAccessFromCode),
+  QUICK_ENTRY_POINT_INFO(pInitializeTypeFromCode),
+  QUICK_ENTRY_POINT_INFO(pResolveStringFromCode),
+  QUICK_ENTRY_POINT_INFO(pSet32Instance),
+  QUICK_ENTRY_POINT_INFO(pSet32Static),
+  QUICK_ENTRY_POINT_INFO(pSet64Instance),
+  QUICK_ENTRY_POINT_INFO(pSet64Static),
+  QUICK_ENTRY_POINT_INFO(pSetObjInstance),
+  QUICK_ENTRY_POINT_INFO(pSetObjStatic),
+  QUICK_ENTRY_POINT_INFO(pGet32Instance),
+  QUICK_ENTRY_POINT_INFO(pGet32Static),
+  QUICK_ENTRY_POINT_INFO(pGet64Instance),
+  QUICK_ENTRY_POINT_INFO(pGet64Static),
+  QUICK_ENTRY_POINT_INFO(pGetObjInstance),
+  QUICK_ENTRY_POINT_INFO(pGetObjStatic),
+  QUICK_ENTRY_POINT_INFO(pHandleFillArrayDataFromCode),
+  QUICK_ENTRY_POINT_INFO(pJniMethodStart),
+  QUICK_ENTRY_POINT_INFO(pJniMethodStartSynchronized),
+  QUICK_ENTRY_POINT_INFO(pJniMethodEnd),
+  QUICK_ENTRY_POINT_INFO(pJniMethodEndSynchronized),
+  QUICK_ENTRY_POINT_INFO(pJniMethodEndWithReference),
+  QUICK_ENTRY_POINT_INFO(pJniMethodEndWithReferenceSynchronized),
+  QUICK_ENTRY_POINT_INFO(pLockObjectFromCode),
+  QUICK_ENTRY_POINT_INFO(pUnlockObjectFromCode),
+  QUICK_ENTRY_POINT_INFO(pCmpgDouble),
+  QUICK_ENTRY_POINT_INFO(pCmpgFloat),
+  QUICK_ENTRY_POINT_INFO(pCmplDouble),
+  QUICK_ENTRY_POINT_INFO(pCmplFloat),
+  QUICK_ENTRY_POINT_INFO(pFmod),
+  QUICK_ENTRY_POINT_INFO(pSqrt),
+  QUICK_ENTRY_POINT_INFO(pL2d),
+  QUICK_ENTRY_POINT_INFO(pFmodf),
+  QUICK_ENTRY_POINT_INFO(pL2f),
+  QUICK_ENTRY_POINT_INFO(pD2iz),
+  QUICK_ENTRY_POINT_INFO(pF2iz),
+  QUICK_ENTRY_POINT_INFO(pIdivmod),
+  QUICK_ENTRY_POINT_INFO(pD2l),
+  QUICK_ENTRY_POINT_INFO(pF2l),
+  QUICK_ENTRY_POINT_INFO(pLdiv),
+  QUICK_ENTRY_POINT_INFO(pLdivmod),
+  QUICK_ENTRY_POINT_INFO(pLmul),
+  QUICK_ENTRY_POINT_INFO(pShlLong),
+  QUICK_ENTRY_POINT_INFO(pShrLong),
+  QUICK_ENTRY_POINT_INFO(pUshrLong),
+  QUICK_ENTRY_POINT_INFO(pInterpreterToInterpreterEntry),
+  QUICK_ENTRY_POINT_INFO(pInterpreterToQuickEntry),
+  QUICK_ENTRY_POINT_INFO(pIndexOf),
+  QUICK_ENTRY_POINT_INFO(pMemcmp16),
+  QUICK_ENTRY_POINT_INFO(pStringCompareTo),
+  QUICK_ENTRY_POINT_INFO(pMemcpy),
+  QUICK_ENTRY_POINT_INFO(pQuickResolutionTrampolineFromCode),
+  QUICK_ENTRY_POINT_INFO(pInvokeDirectTrampolineWithAccessCheck),
+  QUICK_ENTRY_POINT_INFO(pInvokeInterfaceTrampoline),
+  QUICK_ENTRY_POINT_INFO(pInvokeInterfaceTrampolineWithAccessCheck),
+  QUICK_ENTRY_POINT_INFO(pInvokeStaticTrampolineWithAccessCheck),
+  QUICK_ENTRY_POINT_INFO(pInvokeSuperTrampolineWithAccessCheck),
+  QUICK_ENTRY_POINT_INFO(pInvokeVirtualTrampolineWithAccessCheck),
+  QUICK_ENTRY_POINT_INFO(pCheckSuspendFromCode),
+  QUICK_ENTRY_POINT_INFO(pTestSuspendFromCode),
+  QUICK_ENTRY_POINT_INFO(pDeliverException),
+  QUICK_ENTRY_POINT_INFO(pThrowArrayBoundsFromCode),
+  QUICK_ENTRY_POINT_INFO(pThrowDivZeroFromCode),
+  QUICK_ENTRY_POINT_INFO(pThrowNoSuchMethodFromCode),
+  QUICK_ENTRY_POINT_INFO(pThrowNullPointerFromCode),
+  QUICK_ENTRY_POINT_INFO(pThrowStackOverflowFromCode),
+  PORTABLE_ENTRY_POINT_INFO(pPortableResolutionTrampolineFromCode),
 };
-#undef ENTRY_POINT_INFO
+#undef QUICK_ENTRY_POINT_INFO
 
 void Thread::DumpThreadOffset(std::ostream& os, uint32_t offset, size_t size_of_pointers) {
   CHECK_EQ(size_of_pointers, 4U);  // TODO: support 64-bit targets.
@@ -1686,8 +1694,9 @@
 #undef DO_THREAD_OFFSET
 
   size_t entry_point_count = arraysize(gThreadEntryPointInfo);
-  CHECK_EQ(entry_point_count * size_of_pointers, sizeof(QuickEntryPoints));
-  uint32_t expected_offset = OFFSETOF_MEMBER(Thread, entrypoints_);
+  CHECK_EQ(entry_point_count * size_of_pointers,
+           sizeof(QuickEntryPoints) + sizeof(PortableEntryPoints));
+  uint32_t expected_offset = OFFSETOF_MEMBER(Thread, quick_entrypoints_);
   for (size_t i = 0; i < entry_point_count; ++i) {
     CHECK_EQ(gThreadEntryPointInfo[i].offset, expected_offset) << gThreadEntryPointInfo[i].name;
     expected_offset += size_of_pointers;
diff --git a/runtime/thread.h b/runtime/thread.h
index d02ab36..ff0fe22 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -26,9 +26,10 @@
 #include <string>
 
 #include "base/macros.h"
+#include "entrypoints/portable/portable_entrypoints.h"
+#include "entrypoints/quick/quick_entrypoints.h"
 #include "globals.h"
 #include "jvalue.h"
-#include "entrypoints/quick/quick_entrypoints.h"
 #include "locks.h"
 #include "offsets.h"
 #include "root_visitor.h"
@@ -773,9 +774,10 @@
   Closure* checkpoint_function_;
 
  public:
-  // Runtime support function pointers
+  // Entrypoint function pointers
   // TODO: move this near the top, since changing its offset requires all oats to be recompiled!
-  QuickEntryPoints entrypoints_;
+  QuickEntryPoints quick_entrypoints_;
+  PortableEntryPoints portable_entrypoints_;
 
  private:
   // How many times has our pthread key's destructor been called?
diff --git a/runtime/thread_mips.cc b/runtime/thread_mips.cc
deleted file mode 100644
index 0ef26bf..0000000
--- a/runtime/thread_mips.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- */
-
-#include "thread.h"
-
-#include "asm_support.h"
-#include "base/macros.h"
-
-namespace art {
-
-void Thread::InitCpu() {
-  CHECK_EQ(THREAD_FLAGS_OFFSET, OFFSETOF_MEMBER(Thread, state_and_flags_));
-  CHECK_EQ(THREAD_EXCEPTION_OFFSET, OFFSETOF_MEMBER(Thread, exception_));
-}
-
-}  // namespace art