Clear results registers on long jump
Change-Id: Ie4f84ad60b155bc27016ec15d4ecfcce8b0117f1
diff --git a/src/context_arm.cc b/src/context_arm.cc
index c99c774..885a9bc 100644
--- a/src/context_arm.cc
+++ b/src/context_arm.cc
@@ -3,6 +3,7 @@
#include "context_arm.h"
#include "object.h"
+#include "runtime_support.h"
namespace art {
namespace arm {
@@ -49,15 +50,7 @@
void ArmContext::DoLongJump() {
#if defined(__arm__)
- // TODO: Load all GPRs, currently R0 to R3 aren't restored
- asm volatile ( "vldm %2, {%%s0-%%s31}\n"
- "mov %%r0, %0\n"
- "mov %%r1, %1\n"
- "ldm %%r0, {%%r4-%%r14}\n"
- "mov %%pc,%%r1\n"
- : // output
- : "r"(&gprs_[4]), "r"(gprs_[R15]), "r"(&fprs_[S0]) // input
- :); // clobber
+ art_do_long_jump(&gprs_[0], &fprs_[S0]);
#else
UNIMPLEMENTED(FATAL);
#endif
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 23bb2f5..6ebe36e 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -38,6 +38,9 @@
// Return value helper for jobject return types
extern Object* DecodeJObjectInThread(Thread* thread, jobject obj) {
+ if (thread->IsExceptionPending()) {
+ return NULL;
+ }
return thread->DecodeJObject(obj);
}
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 9c7fc3e..c1e0b27 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -37,6 +37,7 @@
extern "C" void* art_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
extern "C" void art_can_put_array_element_from_code(void*, void*);
extern "C" void art_check_cast_from_code(void*, void*);
+ extern "C" void art_do_long_jump(uint32_t*, uint32_t*);
extern "C" void* art_find_instance_field_from_code(uint32_t, void*);
extern "C" void* art_find_static_field_from_code(uint32_t, void*);
extern "C" int32_t art_get32_static_from_code(uint32_t, void*);
diff --git a/src/runtime_support_asm.S b/src/runtime_support_asm.S
index f1a6d63..f65f703 100644
--- a/src/runtime_support_asm.S
+++ b/src/runtime_support_asm.S
@@ -63,6 +63,19 @@
b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
.endm
+ .global art_do_long_jump
+art_do_long_jump:
+ /*
+ * On entry r0 is uint32_t* gprs_ and r1 is uint32_t* fprs_
+ */
+ vldm r1, {s0-s31} @ load all fprs from argument fprs_
+ ldr r2, [r0, #60] @ r2 = r15 (PC from gprs_ 60=4*15)
+ add r0, r0, #12 @ increment r0 to skip gprs_[0..2] 12=4*3
+ ldm r0, {r3-r14} @ load remaining gprs from argument gprs_
+ mov r0, #0 @ clear result registers r0 and r1
+ mov r1, #0
+ bx r2 @ do long jump
+
.global art_deliver_exception_from_code
/*
* Called by managed code, saves mosts registers (forms basis of long jump context) and passes
@@ -380,7 +393,7 @@
* allocate a String and deliver an exception on error. On
* success the String is returned.
*/
- art_resolve_string_from_code:
+art_resolve_string_from_code:
SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP