Fix calling conventions for UnresolvedDirectMethodTrampolineFromCode

Change-Id: I1b35c33d89f0526c80bc8d21e064617d0eac6cd1
diff --git a/src/dalvik_system_VMRuntime.cc b/src/dalvik_system_VMRuntime.cc
index 8d4aa8b..b6a8ed7 100644
--- a/src/dalvik_system_VMRuntime.cc
+++ b/src/dalvik_system_VMRuntime.cc
@@ -114,7 +114,7 @@
   if (targetSdkVersion > 0 && targetSdkVersion <= 13 /* honeycomb-mr2 */) {
     // TODO: running with CheckJNI should override this and force you to obey the strictest rules.
     LOG(INFO) << "Turning on JNI app bug workarounds for target SDK version " << targetSdkVersion << "...";
-    UNIMPLEMENTED(FATAL) << "can we get this as a command-line argument?";
+    UNIMPLEMENTED(WARNING) << "can we get this as a command-line argument?";
     //gDvmJni.work_around_app_jni_bugs = true;
   }
 }
diff --git a/src/dalvik_system_Zygote.cc b/src/dalvik_system_Zygote.cc
index a0fd429..3751e13 100644
--- a/src/dalvik_system_Zygote.cc
+++ b/src/dalvik_system_Zygote.cc
@@ -87,7 +87,8 @@
     // so that it is restarted by init and system server will be restarted
     // from there.
     if (pid == gSystemServerPid) {
-      LOG(FATAL) << "Exit zygote because system server (" << pid << ") has terminated";
+      LOG(ERROR) << "Exit zygote because system server (" << pid << ") has terminated";
+      kill(getpid(), SIGKILL);
     }
   }
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 9b32d69..72720ba 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -308,7 +308,7 @@
   thread->DeliverException();
 }
 
-void* UnresolvedDirectMethodTrampolineFromCode(int32_t method_idx, void* sp, Thread* thread,
+void* UnresolvedDirectMethodTrampolineFromCode(int32_t method_idx, Method** sp, Thread* thread,
                                                Runtime::TrampolineType type) {
   // TODO: this code is specific to ARM
   // On entry the stack pointed by sp is:
@@ -320,15 +320,17 @@
   // | arg1 spill |  |
   // | Method*    | ---
   // | LR         |
+  // | ...        |    callee saves
   // | R3         |    arg3
   // | R2         |    arg2
   // | R1         |    arg1
-  // | R0         | <- sp
-  uintptr_t* regs = reinterpret_cast<uintptr_t*>(sp);
-  Method** caller_sp = reinterpret_cast<Method**>(&regs[5]);
-  uintptr_t caller_pc = regs[4];
-  // Record the last top of the managed stack
-  thread->SetTopOfStack(caller_sp, caller_pc);
+  // | R0         |
+  // | Method*    |  <- sp
+  uintptr_t* regs = reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(sp) + kPointerSize);
+  DCHECK_EQ(48U, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetFrameSizeInBytes());
+  Method** caller_sp = reinterpret_cast<Method**>(reinterpret_cast<byte*>(sp) + 48);
+  uintptr_t caller_pc = regs[10];
+  FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
   // Start new JNI local reference state
   JNIEnvExt* env = thread->GetJniEnv();
   ScopedJniEnvLocalRefState env_state(env);
@@ -387,7 +389,7 @@
     cur_arg = cur_arg + (c == 'J' || c == 'D' ? 2 : 1);
   }
   // Place into local references incoming arguments from the caller's stack arguments
-  cur_arg += 5;  // skip LR, Method* and spills for R1 to R3
+  cur_arg += 11;  // skip LR, Method* and spills for R1 to R3 and callee saves
   while (shorty_index < shorty_len) {
     char c = shorty[shorty_index];
     shorty_index++;
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 6350903..2fc2302 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -18,7 +18,7 @@
 extern Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, bool is_static);
 extern void* FindNativeMethod(Thread* thread);
 extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
-void* UnresolvedDirectMethodTrampolineFromCode(int32_t, void*, Thread*, Runtime::TrampolineType);
+void* UnresolvedDirectMethodTrampolineFromCode(int32_t, Method**, Thread*, Runtime::TrampolineType);
 extern Class* InitializeStaticStorage(uint32_t type_idx, const Method* referrer, Thread* self);
 extern Class* InitializeTypeFromCode(uint32_t type_idx, Method* method);
 uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class);
diff --git a/src/stub_arm.cc b/src/stub_arm.cc
index 3768721..ae9acd62 100644
--- a/src/stub_arm.cc
+++ b/src/stub_arm.cc
@@ -15,24 +15,30 @@
   // | Out args |
   // | Method*  | <- SP on entry
   // | LR       |    return address into caller
+  // | ...      |    callee saves
   // | R3       |    possible argument
   // | R2       |    possible argument
   // | R1       |    possible argument
-  // | R0       |    method index (loaded from code and method array - will be converted to Method*)
-  RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
+  // | R0       |    junk on call to UnresolvedDirectMethodTrampolineFromCode, holds result Method*
+  // | Method*  |    Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
+  // Save callee saves and ready frame for exception delivery
+  RegList save = (1 << R1) | (1 << R2) | (1 << R3) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) |
+                 (1 << R10) | (1 << R11) | (1 << LR);
+  // TODO: enable when GetCalleeSaveMethod is available at stub generation time
+  // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetCoreSpillMask());
   __ PushList(save);
-  __ mov(R1, ShifterOperand(SP));  // Pass address of saved R0... in R1
   __ LoadFromOffset(kLoadWord, R12, TR,
                     OFFSETOF_MEMBER(Thread, pUnresolvedDirectMethodTrampolineFromCode));
   __ mov(R2, ShifterOperand(TR));  // Pass Thread::Current() in R2
   __ LoadImmediate(R3, type);
-  __ IncreaseFrameSize(12);        // 3 words of space for alignment
+  __ IncreaseFrameSize(8);         // 2 words of space for alignment
+  __ mov(R1, ShifterOperand(SP));  // Pass SP
   // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
   __ blx(R12);
   __ mov(R12, ShifterOperand(R0));  // Save code address returned into R12
-  // Restore registers which may have been modified by GC and R0 which will now hold the method*
-  __ DecreaseFrameSize(12);
-  __ PopList(save);
+  // Restore registers which may have been modified by GC, "R0" will hold the Method*
+  __ DecreaseFrameSize(4);
+  __ PopList((1 << R0) | save);
   __ bx(R12);  // Leaf call to method's code
 
   __ bkpt(0);
@@ -54,8 +60,13 @@
   // Save callee saves and ready frame for exception delivery
   RegList save = (1 << R4) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) | (1 << R9) |
                  (1 << R10) | (1 << R11) | (1 << LR);
+  // TODO: enable when GetCalleeSaveMethod is available at stub generation time
+  // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveAll)->GetCoreSpillMask());
   __ PushList(save);         // push {r4-r11, lr} - 9 words of callee saves
+  // TODO: enable when GetCalleeSaveMethod is available at stub generation time
+  // DCHECK_EQ(Runtime::Current()->GetCalleeSaveMethod(Runtime::kSaveAll)->GetFpSpillMask(), 0xFFFFU);
   __ Emit(0xed2d0a20);       // vpush {s0-s31}
+
   __ IncreaseFrameSize(12);  // 3 words of space, bottom word will hold callee save Method*
 
   // R0 is the Method* already
diff --git a/src/thread.cc b/src/thread.cc
index 7dc8104..42d9f1a 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1356,14 +1356,14 @@
 
   void VisitFrame(const Frame& frame, uintptr_t pc) {
     Method* m = frame.GetMethod();
+    if (false) {
+      LOG(INFO) << "Visiting stack roots in " << PrettyMethod(m, false)
+                << "@ PC: " << m->ToDexPC(pc);
+    }
     // Process register map (which native and callee save methods don't have)
     if (!m->IsNative() && !m->IsCalleeSaveMethod()) {
       UniquePtr<art::DexVerifier::RegisterMap> map(art::DexVerifier::GetExpandedRegisterMap(m));
       const uint8_t* reg_bitmap = art::DexVerifier::RegisterMapGetLine(map.get(), m->ToDexPC(pc));
-      if (false) {
-        LOG(INFO) << "Visiting stack roots in " << PrettyMethod(m, false)
-                  << "@ PC: " << m->ToDexPC(pc);
-      }
       CHECK(reg_bitmap != NULL);
       const uint16_t* vmap = m->GetVmapTable();
       // For all dex registers
diff --git a/src/thread.h b/src/thread.h
index 37c1042..e54fea2 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -152,7 +152,7 @@
   void (*pThrowNoSuchMethodFromCode)(int32_t);
   void (*pThrowAbstractMethodErrorFromCode)(Method* method, Thread* thread, Method** sp);
   void (*pUnlockObjectFromCode)(void*);
-  void* (*pUnresolvedDirectMethodTrampolineFromCode)(int32_t, void*, Thread*,
+  void* (*pUnresolvedDirectMethodTrampolineFromCode)(int32_t, Method**, Thread*,
                                                      Runtime::TrampolineType);
 
   class StackVisitor {