summaryrefslogtreecommitdiffstats
path: root/runtime/arch
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-07-29 11:07:13 -0700
committerIan Rogers <irogers@google.com>2013-07-30 16:00:24 -0700
commit7655f29fabc0a12765de828914a18314382e5a35 (patch)
tree219f2df20cf7f053a73a345ae20e131a73759c79 /runtime/arch
parent1a8080d4c2e1772cfcc5e9d6587bc63bba3945d9 (diff)
downloadart-7655f29fabc0a12765de828914a18314382e5a35.zip
art-7655f29fabc0a12765de828914a18314382e5a35.tar.gz
art-7655f29fabc0a12765de828914a18314382e5a35.tar.bz2
Portable refactorings.
Separate quick from portable entrypoints. Move architectural dependencies into arch. Change-Id: I9adbc0a9782e2959fdc3308215f01e3107632b7c
Diffstat (limited to 'runtime/arch')
-rw-r--r--runtime/arch/arm/asm_support_arm.S38
-rw-r--r--runtime/arch/arm/asm_support_arm.h31
-rw-r--r--runtime/arch/arm/entrypoints_init_arm.cc (renamed from runtime/arch/arm/quick_entrypoints_init_arm.cc)160
-rw-r--r--runtime/arch/arm/jni_entrypoints_arm.S65
-rw-r--r--runtime/arch/arm/portable_entrypoints_arm.S96
-rw-r--r--runtime/arch/arm/quick_entrypoints_arm.S127
-rw-r--r--runtime/arch/arm/thread_arm.cc29
-rw-r--r--runtime/arch/mips/asm_support_mips.S41
-rw-r--r--runtime/arch/mips/asm_support_mips.h31
-rw-r--r--runtime/arch/mips/entrypoints_init_mips.cc (renamed from runtime/arch/mips/quick_entrypoints_init_mips.cc)158
-rw-r--r--runtime/arch/mips/jni_entrypoints_mips.S89
-rw-r--r--runtime/arch/mips/portable_entrypoints_mips.S73
-rw-r--r--runtime/arch/mips/quick_entrypoints_mips.S115
-rw-r--r--runtime/arch/mips/thread_mips.cc29
-rw-r--r--runtime/arch/x86/asm_support_x86.S91
-rw-r--r--runtime/arch/x86/asm_support_x86.h27
-rw-r--r--runtime/arch/x86/entrypoints_init_x86.cc (renamed from runtime/arch/x86/quick_entrypoints_init_x86.cc)145
-rw-r--r--runtime/arch/x86/jni_entrypoints_x86.S35
-rw-r--r--runtime/arch/x86/portable_entrypoints_x86.S109
-rw-r--r--runtime/arch/x86/quick_entrypoints_x86.S172
-rw-r--r--runtime/arch/x86/thread_x86.cc139
21 files changed, 1163 insertions, 637 deletions
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/quick_entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc
index 2f66b36..b71a158 100644
--- a/runtime/arch/arm/quick_entrypoints_init_arm.cc
+++ b/runtime/arch/arm/entrypoints_init_arm.cc
@@ -14,8 +14,10 @@
* limitations under the License.
*/
+#include "entrypoints/portable/portable_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
-#include "runtime_support.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "entrypoints/math_entrypoints.h"
namespace art {
@@ -130,108 +132,110 @@ 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) {
+void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
// 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;
+ 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
- points->pInstanceofNonTrivialFromCode = artIsAssignableFromCode;
- points->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
- points->pCheckCastFromCode = art_quick_check_cast_from_code;
+ qpoints->pInstanceofNonTrivialFromCode = artIsAssignableFromCode;
+ qpoints->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
+ qpoints->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;
+ 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
- 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;
+ 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
- points->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
+ qpoints->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;
+ qpoints->pJniMethodStart = JniMethodStart;
+ qpoints->pJniMethodStartSynchronized = JniMethodStartSynchronized;
+ qpoints->pJniMethodEnd = JniMethodEnd;
+ qpoints->pJniMethodEndSynchronized = JniMethodEndSynchronized;
+ qpoints->pJniMethodEndWithReference = JniMethodEndWithReference;
+ qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
// Locks
- points->pLockObjectFromCode = art_quick_lock_object_from_code;
- points->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
+ qpoints->pLockObjectFromCode = art_quick_lock_object_from_code;
+ qpoints->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;
+ 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
- points->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
- points->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
+ qpoints->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
+ qpoints->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
// Intrinsics
- points->pIndexOf = art_quick_indexof;
- points->pMemcmp16 = __memcmp16;
- points->pStringCompareTo = art_quick_string_compareto;
- points->pMemcpy = memcpy;
+ qpoints->pIndexOf = art_quick_indexof;
+ qpoints->pMemcmp16 = __memcmp16;
+ qpoints->pStringCompareTo = art_quick_string_compareto;
+ qpoints->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;
+ 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
- points->pCheckSuspendFromCode = CheckSuspendFromCode;
- points->pTestSuspendFromCode = art_quick_test_suspend;
+ qpoints->pCheckSuspendFromCode = CheckSuspendFromCode;
+ qpoints->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;
+ 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_super_trampoline_with_access_check, artInvoke
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 @@ ENTRY art_quick_do_long_jump
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 @@ ENTRY art_quick_test_suspend
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 @@ ENTRY art_quick_abstract_method_error_stub
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/thread_arm.cc b/runtime/arch/arm/thread_arm.cc
new file mode 100644
index 0000000..ea908be
--- /dev/null
+++ b/runtime/arch/arm/thread_arm.cc
@@ -0,0 +1,29 @@
+/*
+ * 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_arm.h"
+#include "base/logging.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
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/quick_entrypoints_init_mips.cc b/runtime/arch/mips/entrypoints_init_mips.cc
index d494c65..0a62a40 100644
--- a/runtime/arch/mips/quick_entrypoints_init_mips.cc
+++ b/runtime/arch/mips/entrypoints_init_mips.cc
@@ -14,8 +14,10 @@
* limitations under the License.
*/
+#include "entrypoints/portable/portable_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
-#include "runtime_support.h"
+#include "entrypoints/entrypoint_utils.h"
+#include "entrypoints/math_entrypoints.h"
namespace art {
@@ -132,107 +134,109 @@ 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) {
+void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
// 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;
+ 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
- points->pInstanceofNonTrivialFromCode = artIsAssignableFromCode;
- points->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
- points->pCheckCastFromCode = art_quick_check_cast_from_code;
+ qpoints->pInstanceofNonTrivialFromCode = artIsAssignableFromCode;
+ qpoints->pCanPutArrayElementFromCode = art_quick_can_put_array_element_from_code;
+ qpoints->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;
+ 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
- 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;
+ 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
- points->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
+ qpoints->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;
+ qpoints->pJniMethodStart = JniMethodStart;
+ qpoints->pJniMethodStartSynchronized = JniMethodStartSynchronized;
+ qpoints->pJniMethodEnd = JniMethodEnd;
+ qpoints->pJniMethodEndSynchronized = JniMethodEndSynchronized;
+ qpoints->pJniMethodEndWithReference = JniMethodEndWithReference;
+ qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
// Locks
- points->pLockObjectFromCode = art_quick_lock_object_from_code;
- points->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
+ qpoints->pLockObjectFromCode = art_quick_lock_object_from_code;
+ qpoints->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;
+ 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
- points->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
- points->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
+ qpoints->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
+ qpoints->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
// Intrinsics
- points->pIndexOf = art_quick_indexof;
- points->pMemcmp16 = __memcmp16;
- points->pStringCompareTo = art_quick_string_compareto;
- points->pMemcpy = memcpy;
+ qpoints->pIndexOf = art_quick_indexof;
+ qpoints->pMemcmp16 = __memcmp16;
+ qpoints->pStringCompareTo = art_quick_string_compareto;
+ qpoints->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;
+ 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
- points->pCheckSuspendFromCode = CheckSuspendFromCode;
- points->pTestSuspendFromCode = art_quick_test_suspend;
+ qpoints->pCheckSuspendFromCode = CheckSuspendFromCode;
+ qpoints->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;
+ 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_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 @@ END art_quick_invoke_stub
.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 @@ ENTRY art_quick_test_suspend
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 @@ ENTRY art_quick_deoptimize
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 @@ ENTRY art_quick_abstract_method_error_stub
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/arch/mips/thread_mips.cc b/runtime/arch/mips/thread_mips.cc
new file mode 100644
index 0000000..7364de0
--- /dev/null
+++ b/runtime/arch/mips/thread_mips.cc
@@ -0,0 +1,29 @@
+/*
+ * 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_mips.h"
+#include "base/logging.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
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/arch/x86/asm_support_x86.h b/runtime/arch/x86/asm_support_x86.h
new file mode 100644
index 0000000..1092910
--- /dev/null
+++ b/runtime/arch/x86/asm_support_x86.h
@@ -0,0 +1,27 @@
+/*
+ * 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_H_
+#define ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_H_
+
+#include "asm_support.h"
+
+// 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 // ART_RUNTIME_ARCH_X86_ASM_SUPPORT_X86_H_
diff --git a/runtime/arch/x86/quick_entrypoints_init_x86.cc b/runtime/arch/x86/entrypoints_init_x86.cc
index cced916..d47dfef 100644
--- a/runtime/arch/x86/quick_entrypoints_init_x86.cc
+++ b/runtime/arch/x86/entrypoints_init_x86.cc
@@ -14,8 +14,9 @@
* limitations under the License.
*/
+#include "entrypoints/portable/portable_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints.h"
-#include "runtime_support.h"
+#include "entrypoints/entrypoint_utils.h"
namespace art {
@@ -115,107 +116,109 @@ 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) {
+void InitEntryPoints(QuickEntryPoints* qpoints, PortableEntryPoints* ppoints) {
// 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;
+ 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
- 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;
+ 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
- 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;
+ 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
- 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;
+ 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
- points->pHandleFillArrayDataFromCode = art_quick_handle_fill_data_from_code;
+ qpoints->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;
+ qpoints->pJniMethodStart = JniMethodStart;
+ qpoints->pJniMethodStartSynchronized = JniMethodStartSynchronized;
+ qpoints->pJniMethodEnd = JniMethodEnd;
+ qpoints->pJniMethodEndSynchronized = JniMethodEndSynchronized;
+ qpoints->pJniMethodEndWithReference = JniMethodEndWithReference;
+ qpoints->pJniMethodEndWithReferenceSynchronized = JniMethodEndWithReferenceSynchronized;
// Locks
- points->pLockObjectFromCode = art_quick_lock_object_from_code;
- points->pUnlockObjectFromCode = art_quick_unlock_object_from_code;
+ 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.
- 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;
+ 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.
- 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;
+ 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
- points->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
- points->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
+ qpoints->pInterpreterToInterpreterEntry = artInterpreterToInterpreterEntry;
+ qpoints->pInterpreterToQuickEntry = artInterpreterToQuickEntry;
// Intrinsics
- points->pIndexOf = art_quick_indexof;
- points->pMemcmp16 = art_quick_memcmp16;
- points->pStringCompareTo = art_quick_string_compareto;
- points->pMemcpy = art_quick_memcpy;
+ qpoints->pIndexOf = art_quick_indexof;
+ qpoints->pMemcmp16 = art_quick_memcmp16;
+ qpoints->pStringCompareTo = art_quick_string_compareto;
+ qpoints->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;
+ 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
- points->pCheckSuspendFromCode = CheckSuspendFromCode;
- points->pTestSuspendFromCode = art_quick_test_suspend;
+ qpoints->pCheckSuspendFromCode = CheckSuspendFromCode;
+ qpoints->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;
+ 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_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_super_trampoline_with_access_check, artInvoke
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 @@ DEFINE_FUNCTION art_quick_get_obj_static_from_code
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 @@ DEFINE_FUNCTION art_quick_deoptimize
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 @@ DEFINE_FUNCTION art_quick_abstract_method_error_stub
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/arch/x86/thread_x86.cc b/runtime/arch/x86/thread_x86.cc
new file mode 100644
index 0000000..dd3e7dd
--- /dev/null
+++ b/runtime/arch/x86/thread_x86.cc
@@ -0,0 +1,139 @@
+/*
+ * 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 <sys/syscall.h>
+#include <sys/types.h>
+
+#include "asm_support_x86.h"
+#include "base/macros.h"
+#include "thread.h"
+#include "thread_list.h"
+
+#if defined(__APPLE__)
+#include <architecture/i386/table.h>
+#include <i386/user_ldt.h>
+struct descriptor_table_entry_t {
+ uint16_t limit0;
+ uint16_t base0;
+ unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;
+ unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
+} __attribute__((packed));
+#define MODIFY_LDT_CONTENTS_DATA 0
+#else
+#include <asm/ldt.h>
+#endif
+
+namespace art {
+
+void Thread::InitCpu() {
+ static Mutex modify_ldt_lock("modify_ldt lock");
+ MutexLock mu(Thread::Current(), modify_ldt_lock);
+
+ const uintptr_t base = reinterpret_cast<uintptr_t>(this);
+ const size_t limit = kPageSize;
+
+ const int contents = MODIFY_LDT_CONTENTS_DATA;
+ const int seg_32bit = 1;
+ const int read_exec_only = 0;
+ const int limit_in_pages = 0;
+ const int seg_not_present = 0;
+ const int useable = 1;
+
+ int entry_number = -1;
+
+#if defined(__APPLE__)
+ descriptor_table_entry_t entry;
+ memset(&entry, 0, sizeof(entry));
+ entry.limit0 = (limit & 0x0ffff);
+ entry.limit = (limit & 0xf0000) >> 16;
+ entry.base0 = (base & 0x0000ffff);
+ entry.base1 = (base & 0x00ff0000) >> 16;
+ entry.base2 = (base & 0xff000000) >> 24;
+ entry.type = ((read_exec_only ^ 1) << 1) | (contents << 2);
+ entry.s = 1;
+ entry.dpl = 0x3;
+ entry.p = seg_not_present ^ 1;
+ entry.avl = useable;
+ entry.l = 0;
+ entry.d = seg_32bit;
+ entry.g = limit_in_pages;
+
+ entry_number = i386_set_ldt(LDT_AUTO_ALLOC, reinterpret_cast<ldt_entry*>(&entry), 1);
+ if (entry_number == -1) {
+ PLOG(FATAL) << "i386_set_ldt failed";
+ }
+#else
+ // Read current LDT entries.
+ CHECK_EQ((size_t)LDT_ENTRY_SIZE, sizeof(uint64_t));
+ std::vector<uint64_t> ldt(LDT_ENTRIES);
+ size_t ldt_size(sizeof(uint64_t) * ldt.size());
+ memset(&ldt[0], 0, ldt_size);
+ // TODO: why doesn't this return LDT_ENTRY_SIZE * LDT_ENTRIES for the main thread?
+ syscall(__NR_modify_ldt, 0, &ldt[0], ldt_size);
+
+ // Find the first empty slot.
+ for (entry_number = 0; entry_number < LDT_ENTRIES && ldt[entry_number] != 0; ++entry_number) {
+ }
+ if (entry_number >= LDT_ENTRIES) {
+ LOG(FATAL) << "Failed to find a free LDT slot";
+ }
+
+ // Update LDT entry.
+ user_desc ldt_entry;
+ memset(&ldt_entry, 0, sizeof(ldt_entry));
+ ldt_entry.entry_number = entry_number;
+ ldt_entry.base_addr = base;
+ ldt_entry.limit = limit;
+ ldt_entry.seg_32bit = seg_32bit;
+ ldt_entry.contents = contents;
+ ldt_entry.read_exec_only = read_exec_only;
+ ldt_entry.limit_in_pages = limit_in_pages;
+ ldt_entry.seg_not_present = seg_not_present;
+ ldt_entry.useable = useable;
+ CHECK_EQ(0, syscall(__NR_modify_ldt, 1, &ldt_entry, sizeof(ldt_entry)));
+ entry_number = ldt_entry.entry_number;
+#endif
+
+ // Change %fs to be new LDT entry.
+ uint16_t table_indicator = 1 << 2; // LDT
+ uint16_t rpl = 3; // Requested privilege level
+ uint16_t selector = (entry_number << 3) | table_indicator | rpl;
+ // TODO: use our assembler to generate code
+ __asm__ __volatile__("movw %w0, %%fs"
+ : // output
+ : "q"(selector) // input
+ :); // clobber
+
+ // Allow easy indirection back to Thread*.
+ self_ = this;
+
+ // Sanity check that reads from %fs point to this Thread*.
+ Thread* self_check;
+ // TODO: use our assembler to generate code
+ CHECK_EQ(THREAD_SELF_OFFSET, OFFSETOF_MEMBER(Thread, self_));
+ __asm__ __volatile__("movl %%fs:(%1), %0"
+ : "=r"(self_check) // output
+ : "r"(THREAD_SELF_OFFSET) // input
+ :); // clobber
+ CHECK_EQ(self_check, this);
+
+ // Sanity check other offsets.
+ CHECK_EQ(THREAD_EXCEPTION_OFFSET, OFFSETOF_MEMBER(Thread, exception_));
+}
+
+} // namespace art