summaryrefslogtreecommitdiff
path: root/runtime/stack.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/stack.h')
-rw-r--r--runtime/stack.h153
1 files changed, 55 insertions, 98 deletions
diff --git a/runtime/stack.h b/runtime/stack.h
index e58caeee79..8e5da3587d 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -54,50 +54,6 @@ enum VRegKind {
kUndefined,
};
-/**
- * @brief Represents the virtual register numbers that denote special meaning.
- * @details This is used to make some virtual register numbers to have specific
- * semantic meaning. This is done so that the compiler can treat all virtual
- * registers the same way and only special case when needed. For example,
- * calculating SSA does not care whether a virtual register is a normal one or
- * a compiler temporary, so it can deal with them in a consistent manner. But,
- * for example if backend cares about temporaries because it has custom spill
- * location, then it can special case them only then.
- */
-enum VRegBaseRegNum : int {
- /**
- * @brief Virtual registers originating from dex have number >= 0.
- */
- kVRegBaseReg = 0,
-
- /**
- * @brief Invalid virtual register number.
- */
- kVRegInvalid = -1,
-
- /**
- * @brief Used to denote the base register for compiler temporaries.
- * @details Compiler temporaries are virtual registers not originating
- * from dex but that are created by compiler. All virtual register numbers
- * that are <= kVRegTempBaseReg are categorized as compiler temporaries.
- */
- kVRegTempBaseReg = -2,
-
- /**
- * @brief Base register of temporary that holds the method pointer.
- * @details This is a special compiler temporary because it has a specific
- * location on stack.
- */
- kVRegMethodPtrBaseReg = kVRegTempBaseReg,
-
- /**
- * @brief Base register of non-special compiler temporary.
- * @details A non-special compiler temporary is one whose spill location
- * is flexible.
- */
- kVRegNonSpecialTempBaseReg = -3,
-};
-
// A reference from the shadow stack to a MirrorType object within the Java heap.
template<class MirrorType>
class MANAGED StackReference : public mirror::ObjectReference<false, MirrorType> {
@@ -612,75 +568,76 @@ class StackVisitor {
/*
* 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 an invalid Dalvik register, (reg == -2) denotes Method*
- * and (reg <= -3) denotes a compiler temporary. A compiler temporary
- * can be thought of as a virtual register that does not exist in the
- * dex but holds intermediate values to help optimizations and code
- * generation. A special compiler temporary is one whose location
- * in frame is well known while non-special ones do not have a requirement
- * on location in frame as long as code generator itself knows how
- * to access them.
+ * Note that (reg == -1) denotes an invalid Dalvik register. For the
+ * positive values, the Dalvik registers come first, followed by the
+ * Method*, followed by other special temporaries if any, followed by
+ * regular compiler temporary. As of now we only have the Method* as
+ * as a special compiler temporary.
+ * A compiler temporary can be thought of as a virtual register that
+ * does not exist in the dex but holds intermediate values to help
+ * optimizations and code generation. A special compiler temporary is
+ * one whose location in frame is well known while non-special ones
+ * do not have a requirement on location in frame as long as code
+ * generator itself knows how to access them.
*
- * +---------------------------+
- * | IN[ins-1] | {Note: resides in caller's frame}
- * | . |
- * | IN[0] |
- * | caller's ArtMethod | ... StackReference<ArtMethod>
- * +===========================+ {Note: start of callee's frame}
- * | core callee-save spill | {variable sized}
- * +---------------------------+
- * | fp callee-save spill |
- * +---------------------------+
- * | filler word | {For compatibility, if V[locals-1] used as wide
- * +---------------------------+
- * | V[locals-1] |
- * | V[locals-2] |
- * | . |
- * | . | ... (reg == 2)
- * | V[1] | ... (reg == 1)
- * | V[0] | ... (reg == 0) <---- "locals_start"
- * +---------------------------+
- * | Compiler temp region | ... (reg <= -3)
- * | |
- * | |
- * +---------------------------+
- * | stack alignment padding | {0 to (kStackAlignWords-1) of padding}
- * +---------------------------+
- * | OUT[outs-1] |
- * | OUT[outs-2] |
- * | . |
- * | OUT[0] |
- * | StackReference<ArtMethod> | ... (reg == -2) <<== sp, 16-byte aligned
- * +===========================+
+ * +-------------------------------+
+ * | IN[ins-1] | {Note: resides in caller's frame}
+ * | . |
+ * | IN[0] |
+ * | caller's ArtMethod | ... StackReference<ArtMethod>
+ * +===============================+ {Note: start of callee's frame}
+ * | core callee-save spill | {variable sized}
+ * +-------------------------------+
+ * | fp callee-save spill |
+ * +-------------------------------+
+ * | filler word | {For compatibility, if V[locals-1] used as wide
+ * +-------------------------------+
+ * | V[locals-1] |
+ * | V[locals-2] |
+ * | . |
+ * | . | ... (reg == 2)
+ * | V[1] | ... (reg == 1)
+ * | V[0] | ... (reg == 0) <---- "locals_start"
+ * +-------------------------------+
+ * | stack alignment padding | {0 to (kStackAlignWords-1) of padding}
+ * +-------------------------------+
+ * | Compiler temp region | ... (reg >= max_num_special_temps)
+ * | . |
+ * | . |
+ * | V[max_num_special_temps + 1] |
+ * | V[max_num_special_temps + 0] |
+ * +-------------------------------+
+ * | OUT[outs-1] |
+ * | OUT[outs-2] |
+ * | . |
+ * | OUT[0] |
+ * | StackReference<ArtMethod> | ... (reg == num_total_code_regs == special_temp_value) <<== sp, 16-byte aligned
+ * +===============================+
*/
static int GetVRegOffset(const DexFile::CodeItem* code_item,
uint32_t core_spills, uint32_t fp_spills,
size_t frame_size, int reg, InstructionSet isa) {
DCHECK_EQ(frame_size & (kStackAlignment - 1), 0U);
- DCHECK_NE(reg, static_cast<int>(kVRegInvalid));
+ DCHECK_NE(reg, -1);
int spill_size = POPCOUNT(core_spills) * GetBytesPerGprSpillLocation(isa)
+ POPCOUNT(fp_spills) * GetBytesPerFprSpillLocation(isa)
+ sizeof(uint32_t); // Filler.
- int num_ins = code_item->ins_size_;
- int num_regs = code_item->registers_size_ - num_ins;
- int locals_start = frame_size - spill_size - num_regs * sizeof(uint32_t);
- if (reg == static_cast<int>(kVRegMethodPtrBaseReg)) {
+ int num_regs = code_item->registers_size_ - code_item->ins_size_;
+ int temp_threshold = code_item->registers_size_;
+ const int max_num_special_temps = 1;
+ if (reg == temp_threshold) {
// The current method pointer corresponds to special location on stack.
return 0;
- } else if (reg <= static_cast<int>(kVRegNonSpecialTempBaseReg)) {
+ } else if (reg >= temp_threshold + max_num_special_temps) {
/*
* Special temporaries may have custom locations and the logic above deals with that.
- * However, non-special temporaries are placed relative to the locals. Since the
- * virtual register numbers for temporaries "grow" in negative direction, reg number
- * will always be <= to the temp base reg. Thus, the logic ensures that the first
- * temp is at offset -4 bytes from locals, the second is at -8 bytes from locals,
- * and so on.
+ * However, non-special temporaries are placed relative to the outs.
*/
- int relative_offset =
- (reg + std::abs(static_cast<int>(kVRegNonSpecialTempBaseReg)) - 1) * sizeof(uint32_t);
- return locals_start + relative_offset;
+ int temps_start = sizeof(StackReference<mirror::ArtMethod>) + code_item->outs_size_ * sizeof(uint32_t);
+ int relative_offset = (reg - (temp_threshold + max_num_special_temps)) * sizeof(uint32_t);
+ return temps_start + relative_offset;
} else if (reg < num_regs) {
+ int locals_start = frame_size - spill_size - num_regs * sizeof(uint32_t);
return locals_start + (reg * sizeof(uint32_t));
} else {
// Handle ins.