Fix JNI compiler for synchronized methods.

Calls to the monitor enter/exit routines were passing the JNI env with
the iterator in the wrong position. Reset the iterator to make sure it
is in the correct position for the monitor enter/exit call.

Also fix clobbering of arguments in registers when calling monitor enter
for synchronized methods on ARM.

Also some tidying of code/comments.

Change-Id: I5bf1dd7e65d925e768411cb5865919ee5f54edbf
diff --git a/src/assembler_arm.cc b/src/assembler_arm.cc
index 9b8cc3a..c13db39 100644
--- a/src/assembler_arm.cc
+++ b/src/assembler_arm.cc
@@ -1413,34 +1413,50 @@
   mov(rd, ShifterOperand(rm, ROR, 0), cond);
 }
 
-// Emit code that will create an activation on the stack
-void Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg) {
-  CHECK(IsAligned(frame_size, 16));
-  // TODO: use stm/ldm
+void Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
+                           const std::vector<ManagedRegister>& spill_regs) {
+  CHECK(IsAligned(frame_size, kStackAlignment));
+  CHECK_EQ(R0, method_reg.AsCoreRegister());
   AddConstant(SP, -frame_size);
-  StoreToOffset(kStoreWord, LR, SP, frame_size - 4);
-  StoreToOffset(kStoreWord, method_reg.AsCoreRegister(), SP, 0);
+  RegList spill_list = 1 << R0 | 1 << LR;
+  for(size_t i = 0; i < spill_regs.size(); i++) {
+    Register reg = spill_regs.at(i).AsCoreRegister();
+    // check assumption LR is the last register that gets spilled
+    CHECK_LT(reg, LR);
+    spill_list |= 1 << reg;
+  }
+  // Store spill list from (low to high number register) starting at SP
+  // incrementing after each store but not updating SP
+  stm(IA, SP, spill_list, AL);
 }
 
-// Emit code that will remove an activation from the stack
-void Assembler::RemoveFrame(size_t frame_size) {
-  CHECK(IsAligned(frame_size, 16));
-  LoadFromOffset(kLoadWord, LR, SP, frame_size - 4);
+void Assembler::RemoveFrame(size_t frame_size,
+                            const std::vector<ManagedRegister>& spill_regs) {
+  CHECK(IsAligned(frame_size, kStackAlignment));
+  // Reload LR. TODO: reload any saved callee saves from spill_regs
+  LoadFromOffset(kLoadWord, LR, SP, (spill_regs.size() + 1) * kPointerSize);
   AddConstant(SP, frame_size);
   mov(PC, ShifterOperand(LR));
 }
 
+void Assembler::FillFromSpillArea(const std::vector<ManagedRegister>& spill_regs,
+                                  size_t displacement) {
+  for(size_t i = 0; i < spill_regs.size(); i++) {
+    Register reg = spill_regs.at(i).AsCoreRegister();
+    LoadFromOffset(kLoadWord, reg, SP, displacement + ((i + 1) * kPointerSize));
+  }
+}
+
 void Assembler::IncreaseFrameSize(size_t adjust) {
-  CHECK(IsAligned(adjust, 16));
+  CHECK(IsAligned(adjust, kStackAlignment));
   AddConstant(SP, -adjust);
 }
 
 void Assembler::DecreaseFrameSize(size_t adjust) {
-  CHECK(IsAligned(adjust, 16));
+  CHECK(IsAligned(adjust, kStackAlignment));
   AddConstant(SP, adjust);
 }
 
-// Store bytes from the given register onto the stack
 void Assembler::Store(FrameOffset dest, ManagedRegister src, size_t size) {
   if (src.IsNoRegister()) {
     CHECK_EQ(0u, size);
@@ -1671,9 +1687,6 @@
   // TODO: place reference map on call
 }
 
-// Generate code to check if Thread::Current()->suspend_count_ is non-zero
-// and branch to a SuspendSlowPath if it is. The SuspendSlowPath will continue
-// at the next instruction.
 void Assembler::SuspendPoll(ManagedRegister scratch, ManagedRegister return_reg,
                             FrameOffset return_save_location,
                             size_t return_size) {
@@ -1703,8 +1716,6 @@
   sp_asm->b(&continuation_);
 }
 
-// Generate code to check if Thread::Current()->exception_ is non-null
-// and branch to a ExceptionSlowPath if it is.
 void Assembler::ExceptionPoll(ManagedRegister scratch) {
   ExceptionSlowPath* slow = new ExceptionSlowPath();
   buffer_.EnqueueSlowPath(slow);