Frame layout change

This CL slightly changes the frame layout to remove an old unnecessary
slot, allow for the inclusion of compiler-generated temps and
unifies all variable offset calculation into a single function shared
by the compilers and the runtime system.

   o Update the GetVRegOffset function in stack.cc to understand the
     new layout.

   o Remove compiler-private offset calculation code and route
     everything through the shared GetVRegOffset in thread.cc.

   o Remove "filler word" that existed immediately after the last
     Dalvik local.  This was there to address an initial concern that
     I had about a single argument register being reused later as a
     long.  Now convinced that it won't happen.

   o Extend the old "padding" region to include compiler-created temps
     that can appear to the rest of the rest of the system as
     Dalvik registers.  The new temps will have Dalvik register numbers
     of -2 and lower.

   o Treat Method* for the current method as a special Dalvik register
     denoted by reg number -1.

Change-Id: I5b5f3aef9c6a01d3a647ced6ec06981ed228c785
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index c6d14c3..58eba7c 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -367,9 +367,7 @@
     int numRegs;            // Unlike numDalvikRegisters, does not include ins
     int numCoreSpills;
     int numFPSpills;
-    int numPadding;         // # of 4-byte padding cells
-    int regsOffset;         // sp-relative offset to beginning of Dalvik regs
-    int insOffset;          // sp-relative offset to beginning of Dalvik ins
+    int numCompilerTemps;
     int frameSize;
     unsigned int coreSpillMask;
     unsigned int fpSpillMask;
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index abc573e..5176edc 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -406,15 +406,12 @@
     }
 
     /* Figure out the frame size */
-    static const int kStackAlignWords = kStackAlignment/sizeof(uint32_t);
-    cUnit->numPadding = (kStackAlignWords -
-        (cUnit->numCoreSpills + cUnit->numFPSpills + cUnit->numRegs +
-             cUnit->numOuts + 2)) & (kStackAlignWords - 1);
-    cUnit->frameSize = (cUnit->numCoreSpills + cUnit->numFPSpills +
-                        cUnit->numRegs + cUnit->numOuts +
-                        cUnit->numPadding + 2) * 4;
-    cUnit->insOffset = cUnit->frameSize + 4;
-    cUnit->regsOffset = (cUnit->numOuts + cUnit->numPadding + 1) * 4;
+    static const uint32_t kAlignMask = kStackAlignment - 1;
+    uint32_t size = (cUnit->numCoreSpills + cUnit->numFPSpills +
+                     cUnit->numRegs + cUnit->numOuts + cUnit->numCompilerTemps +
+                     1 /* curMethod* */) * sizeof(uint32_t);
+    /* Align and set */
+    cUnit->frameSize = (size + kAlignMask) & ~(kAlignMask);
 }
 
 }  // namespace art
diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc
index ad02c39..bbf7c38 100644
--- a/src/compiler/codegen/CodegenUtil.cc
+++ b/src/compiler/codegen/CodegenUtil.cc
@@ -372,10 +372,7 @@
     LOG(INFO) << "Outs                 : " << cUnit->numOuts;
     LOG(INFO) << "CoreSpills           : " << cUnit->numCoreSpills;
     LOG(INFO) << "FPSpills             : " << cUnit->numFPSpills;
-    LOG(INFO) << "Padding              : " << cUnit->numPadding;
     LOG(INFO) << "Frame size           : " << cUnit->frameSize;
-    LOG(INFO) << "Start of ins         : " << cUnit->insOffset;
-    LOG(INFO) << "Start of regs        : " << cUnit->regsOffset;
     LOG(INFO) << "code size is " << cUnit->totalSize <<
         " bytes, Dalvik size is " << insnsSize * 2;
     LOG(INFO) << "expansion factor: " <<
diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc
index cfda721..b5ebf65 100644
--- a/src/compiler/codegen/RallocUtil.cc
+++ b/src/compiler/codegen/RallocUtil.cc
@@ -1217,8 +1217,8 @@
 /* Returns sp-relative offset in bytes for a VReg */
 extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
 {
-    return (vReg < cUnit->numRegs) ? cUnit->regsOffset + (vReg << 2) :
-            cUnit->insOffset + ((vReg - cUnit->numRegs) << 2);
+    return Frame::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
+                                cUnit->fpSpillMask, cUnit->frameSize, vReg);
 }
 
 /* Returns sp-relative offset in bytes for a SReg */
diff --git a/src/stack.cc b/src/stack.cc
index 4623ec1..da5c31e 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -49,21 +49,60 @@
   *reinterpret_cast<uintptr_t*>(pc_addr) = pc;
 }
 
-/* Return sp-relative offset in bytes using Method* */
-static int GetVRegOffset(const DexFile::CodeItem* code_item,
+/*
+ * Return sp-relative offset for a Dalvik virtual register, compiler
+ * spill or Method* in bytes using Method*.
+ * Note that (reg >= 0) refers to a Dalvik register, (reg == -1)
+ * denotes Method* and (reg <= -2) denotes a compiler temp.
+ *
+ *     +------------------------+
+ *     | IN[ins-1]              |  {Note: resides in caller's frame}
+ *     |       .                |
+ *     | IN[0]                  |
+ *     | caller's Method*       |
+ *     +========================+  {Note: start of callee's frame}
+ *     | core callee-save spill |  {variable sized}
+ *     +------------------------+
+ *     | fp calle-save spill    |
+ *     +------------------------+
+ *     | V[locals-1]            |
+ *     | V[locals-2]            |
+ *     |      .                 |
+ *     |      .                 |  ... (reg == 2)
+ *     | V[1]                   |  ... (reg == 1)
+ *     | V[0]                   |  ... (reg == 0) <---- "locals_start"
+ *     +------------------------+
+ *     | Compiler temps         |  ... (reg == -2)
+ *     |                        |  ... (reg == -3)
+ *     |                        |  ... (reg == -4)
+ *     +------------------------+
+ *     | stack alignment padding|  {0 to (kStackAlignWords-1) of padding}
+ *     +------------------------+
+ *     | OUT[outs-1]            |
+ *     | OUT[outs-2]            |
+ *     |       .                |
+ *     | OUT[0]                 |
+ *     | curMethod*             |  ... (reg == -1) <<== sp, 16-byte aligned
+ *     +========================+
+ */
+int Frame::GetVRegOffset(const DexFile::CodeItem* code_item,
                          uint32_t core_spills, uint32_t fp_spills,
                          size_t frame_size, int reg)
 {
-  static const int kStackAlignWords = kStackAlignment/sizeof(uint32_t);
-  int numIns = code_item->ins_size_;
-  int numRegs = code_item->registers_size_ - numIns;
-  int numOuts = code_item->outs_size_;
-  int numSpills = __builtin_popcount(core_spills) + __builtin_popcount(fp_spills);
-  int numPadding = (kStackAlignWords - (numSpills + numRegs + numOuts + 2)) & (kStackAlignWords - 1);
-  int regsOffset = (numOuts + numPadding + 1) * 4;
-  int insOffset = frame_size + 4;
-  return (reg < numRegs) ? regsOffset + (reg << 2) :
-  insOffset + ((reg - numRegs) << 2);
+  DCHECK_EQ( frame_size & (kStackAlignment - 1), 0U);
+  int num_spills = __builtin_popcount(core_spills) + __builtin_popcount(fp_spills);
+  int num_ins = code_item->ins_size_;
+  int num_regs = code_item->registers_size_ - num_ins;
+  int locals_start = frame_size - ((num_spills + num_regs) * sizeof(uint32_t));
+  if (reg == -1) {
+    return 0;  // Method*
+  } else if (reg <= -2) {
+    return locals_start - ((reg + 1) * sizeof(uint32_t));  // Compiler temp
+  } else if (reg < num_regs) {
+    return locals_start + (reg * sizeof(uint32_t));        // Dalvik local reg
+  } else {
+    return frame_size + ((reg - num_regs) * sizeof(uint32_t)) + sizeof(uint32_t); // Dalvik in
+  }
 }
 
 uint32_t Frame::GetVReg(const DexFile::CodeItem* code_item, uint32_t core_spills,
diff --git a/src/stack.h b/src/stack.h
index 382ad24..9093cb1 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -59,6 +59,8 @@
 
   uintptr_t LoadCalleeSave(int num) const;
 
+  static int GetVRegOffset(const DexFile::CodeItem* code_item, uint32_t core_spills,
+                           uint32_t fp_spills, size_t frame_size, int reg);
 
   uint32_t GetVReg(const DexFile::CodeItem* code_item, uint32_t core_spills, uint32_t fp_spills,
                     size_t frame_size, int vreg) const;