Callee-save frame fix
Previously, the callee-frame stubs tried to be a little too efficient
in stack usage by re-using the storage allocated for the Method* to pass
an argument. Unfortunately, if the compiler decided to do a tail-call
optimization on the called routine, it could end up re-using that same
slot for outgoing arguments (thus clobbering the Method*, and breaking
a subsequent stack crawl).
This CL fixes the problem by not re-using the Method* slot (at the cost
of a few extra instructions and 16 bytes of stack).
Change-Id: Ibce43ed84f81a8e332c2e77674e355c338efaaf0
diff --git a/src/oat/runtime/arm/runtime_support_arm.S b/src/oat/runtime/arm/runtime_support_arm.S
index 09b26b9..1978a73 100644
--- a/src/oat/runtime/arm/runtime_support_arm.S
+++ b/src/oat/runtime/arm/runtime_support_arm.S
@@ -177,8 +177,10 @@
SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME @ save callee saves in case allocation triggers GC
ldr r2, [sp, #48] @ pass caller Method*
mov r3, r9 @ pass Thread::Current
- str sp, [sp, #0] @ pass SP
+ mov r12, sp
+ str r12, [sp, #-16]! @ expand the frame and pass SP
bl \cxx_name @ (method_idx, this, caller, Thread*, SP)
+ add sp, #16 @ strip the extra frame
mov r12, r1 @ save Method*->code_
RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
cmp r0, #0 @ did we find the target?
@@ -440,8 +442,10 @@
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r2, [sp, #32] @ pass referrer
mov r3, r9 @ pass Thread::Current
- str sp, [sp, #0] @ pass SP
+ mov r12, sp
+ str r12, [sp, #-16]! @ expand the frame and pass SP
bl artGet32InstanceFromCode @ (field_idx, Object*, referrer, Thread*, SP)
+ add sp, #16 @ strip the extra frame
ldr r12, [r9, #THREAD_EXCEPTION_OFFSET] @ load Thread::Current()->exception_
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r12, #0 @ success if no exception is pending
@@ -458,8 +462,10 @@
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r2, [sp, #32] @ pass referrer
mov r3, r9 @ pass Thread::Current
- str sp, [sp, #0] @ pass SP
+ mov r12, sp
+ str r12, [sp, #-16]! @ expand the frame and pass SP
bl artGet64InstanceFromCode @ (field_idx, Object*, referrer, Thread*, SP)
+ add sp, #16 @ strip the extra frame
ldr r12, [r9, #THREAD_EXCEPTION_OFFSET] @ load Thread::Current()->exception_
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r12, #0 @ success if no exception is pending
@@ -476,8 +482,10 @@
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r2, [sp, #32] @ pass referrer
mov r3, r9 @ pass Thread::Current
- str sp, [sp, #0] @ pass SP
+ mov r12, sp
+ str r12, [sp, #-16]! @ expand the frame and pass SP
bl artGetObjInstanceFromCode @ (field_idx, Object*, referrer, Thread*, SP)
+ add sp, #16 @ strip the extra frame
ldr r12, [r9, #THREAD_EXCEPTION_OFFSET] @ load Thread::Current()->exception_
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r12, #0 @ success if no exception is pending
@@ -494,8 +502,10 @@
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r2, [sp, #32] @ pass referrer
mov r3, r9 @ pass Thread::Current
- str sp, [sp, #0] @ pass SP
+ mov r12, sp
+ str r12, [sp, #-16]! @ expand the frame and pass SP
bl artSet32StaticFromCode @ (field_idx, new_val, referrer, Thread*, SP)
+ add sp, #16 @ strip the extra frame
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success if result is 0
bxeq lr @ return on success
@@ -533,8 +543,10 @@
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
ldr r2, [sp, #32] @ pass referrer
mov r3, r9 @ pass Thread::Current
- str sp, [sp, #0] @ pass SP
+ mov r12, sp
+ str r12, [sp, #-16]! @ expand the frame and pass SP
bl artSetObjStaticFromCode @ (field_idx, new_val, referrer, Thread*, SP)
+ add sp, #16 @ strip the extra frame
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success if result is 0
bxeq lr @ return on success
@@ -658,9 +670,11 @@
art_alloc_array_from_code:
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r3, r9 @ pass Thread::Current
- str sp, [sp, #0] @ pass SP
+ mov r12, sp
+ str r12, [sp, #-16]! @ expand the frame and pass SP
@ artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count, Thread*, SP)
bl artAllocArrayFromCode
+ add sp, #16 @ strip the extra frame
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
@@ -676,9 +690,11 @@
art_alloc_array_from_code_with_access_check:
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r3, r9 @ pass Thread::Current
- str sp, [sp, #0] @ pass SP
+ mov r12, sp
+ str r12, [sp, #-16]! @ expand the frame and pass SP
@ artAllocArrayFromCodeWithAccessCheck(type_idx, method, component_count, Thread*, SP)
bl artAllocArrayFromCodeWithAccessCheck
+ add sp, #16 @ strip the extra frame
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
@@ -693,9 +709,11 @@
art_check_and_alloc_array_from_code:
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r3, r9 @ pass Thread::Current
- str sp, [sp, #0] @ pass SP
+ mov r12, sp
+ str r12, [sp, #-16]! @ expand the frame and pass SP
@ artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t count, Thread* , SP)
bl artCheckAndAllocArrayFromCode
+ add sp, #16 @ strip the extra frame
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success
@@ -710,9 +728,11 @@
art_check_and_alloc_array_from_code_with_access_check:
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r3, r9 @ pass Thread::Current
- str sp, [sp, #0] @ pass SP
+ mov r12, sp
+ str r12, [sp, #-16]! @ expand the frame and pass SP
@ artCheckAndAllocArrayFromCodeWithAccessCheck(type_idx, method, count, Thread* , SP)
bl artCheckAndAllocArrayFromCodeWithAccessCheck
+ add sp, #16 @ strip the extra frame
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success if result is non-null
bxne lr @ return on success