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;