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/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,