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 23bb2f514..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