Index: src/compiler/frame.h |
diff --git a/src/compiler/frame.h b/src/compiler/frame.h |
index f901b1e2b3402bc662023b1618cefa4702cc7cc5..aa823b6ba8ad0f885c68ed6dfe91f460a48e11c2 100644 |
--- a/src/compiler/frame.h |
+++ b/src/compiler/frame.h |
@@ -6,26 +6,93 @@ |
#define V8_COMPILER_FRAME_H_ |
#include "src/bit-vector.h" |
+#include "src/frames.h" |
namespace v8 { |
namespace internal { |
namespace compiler { |
-// Collects the spill slot requirements and the allocated general and double |
-// registers for a compiled function. Frames are usually populated by the |
-// register allocator and are used by Linkage to generate code for the prologue |
-// and epilogue to compiled code. |
+// Collects the spill slot and other frame slot requirements for a compiled |
+// function. Frames are usually populated by the register allocator and are used |
+// by Linkage to generate code for the prologue and epilogue to compiled code. |
+// |
+// Frames are divided up into three regions. The first is the fixed header, |
+// which always has a constant size and can be predicted before code generation |
+// begins depending on the type of code being generated. The second is the |
+// region for spill slots, which is immediately below the fixed header and grows |
+// as the register allocator needs to spill to the stack and asks the frame for |
+// more space. The third region, which contains the callee-saved registers must |
+// be reserved after register allocation, since its size can only be precisely |
+// determined after register allocation once the number of used callee-saved |
+// register is certain. |
+// |
+// Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume |
+// two slots. |
+// |
+// Stack slot indices >= 0 access the callee stack with slot 0 corresponding to |
+// the callee's saved return address and 1 corresponding to the saved frame |
+// pointer. Some frames have additional information stored in the fixed header, |
+// for example JSFunctions store the function context and marker in the fixed |
+// header, with slot index 2 corresponding to the current function context and 3 |
+// corresponding to the frame marker/JSFunction. The frame region immediately |
+// below the fixed header contains spill slots starting a 4 for JsFunctions. The |
+// callee-saved frame region below that starts at 4+spilled_slot_count. Callee |
+// stack slots corresponding to parameters are accessible through negative slot |
+// ids. |
+// |
+// Every slot of a caller or callee frame is accessible by the register |
+// allocator and gap resolver with a SpillSlotOperand containing its |
+// corresponding slot id. |
+// |
+// Below an example JSFunction Frame with slot ids, frame regions and contents: |
+// |
+// slot JS frame |
+// +-----------------+---------------------------- |
+// -n-1 | parameter 0 | ^ |
+// |- - - - - - - - -| | |
+// -n | | Caller |
+// ... | ... | frame slots |
+// -2 | parameter n-1 | (slot < 0) |
+// |- - - - - - - - -| | |
+// -1 | parameter n | v |
+// -----+-----------------+---------------------------- |
+// 0 | return addr | ^ ^ |
+// |- - - - - - - - -| | | |
+// 1 | saved frame ptr | Fixed | |
+// |- - - - - - - - -| Header <-- frame ptr | |
+// 2 | Context | | | |
+// |- - - - - - - - -| | | |
+// 3 |JSFunction/Marker| v | |
+// +-----------------+---- | |
+// 4 | spill 1 | ^ Callee |
+// |- - - - - - - - -| | frame slots |
+// ... | ... | Spill slots (slot >= 0) |
+// |- - - - - - - - -| | | |
+// m+4 | spill m | v | |
+// +-----------------+---- | |
+// m+5 | callee-saved 1 | ^ | |
+// |- - - - - - - - -| | | |
+// | ... | Callee-saved | |
+// |- - - - - - - - -| | | |
+// m+r+4 | callee-saved r | v v |
+// -----+-----------------+----- <-- stack ptr --------- |
+// |
class Frame : public ZoneObject { |
public: |
- Frame() |
- : register_save_area_size_(0), |
- spill_slot_count_(0), |
- osr_stack_slot_count_(0), |
- allocated_registers_(NULL), |
- allocated_double_registers_(NULL), |
- pc_on_stack_(true) {} |
+ explicit Frame(int fixed_frame_size_in_slots); |
- inline int GetSpillSlotCount() { return spill_slot_count_; } |
+ inline int GetTotalFrameSlotCount() { return frame_slot_count_; } |
+ |
+ inline int GetSavedCalleeRegisterSlotCount() { |
+ return spilled_callee_register_slot_count_; |
+ } |
+ inline int GetSpillSlotCount() { return stack_slot_count_; } |
+ |
+ inline void SetElidedFrameSizeInSlots(int slots) { |
+ DCHECK_EQ(0, spilled_callee_register_slot_count_); |
+ DCHECK_EQ(0, stack_slot_count_); |
+ frame_slot_count_ = slots; |
+ } |
void SetAllocatedRegisters(BitVector* regs) { |
DCHECK(allocated_registers_ == NULL); |
@@ -41,48 +108,52 @@ class Frame : public ZoneObject { |
return !allocated_double_registers_->IsEmpty(); |
} |
- void SetRegisterSaveAreaSize(int size) { |
- DCHECK(IsAligned(size, kPointerSize)); |
- register_save_area_size_ = size; |
+ int AlignSavedCalleeRegisterSlots() { |
+ DCHECK_EQ(0, spilled_callee_register_slot_count_); |
+ int frame_slot_count_before = frame_slot_count_; |
+ frame_slot_count_ = RoundUp(frame_slot_count_, 2); |
+ return frame_slot_count_before - frame_slot_count_; |
} |
- int GetRegisterSaveAreaSize() { return register_save_area_size_; } |
+ void AllocateSavedCalleeRegisterSlots(int count) { |
+ frame_slot_count_ += count; |
+ spilled_callee_register_slot_count_ += count; |
+ } |
- // OSR stack slots, including locals and expression stack slots. |
- void SetOsrStackSlotCount(int slots) { |
- DCHECK(slots >= 0); |
- osr_stack_slot_count_ = slots; |
+ int AllocateSpillSlot(int width) { |
+ DCHECK_EQ(0, spilled_callee_register_slot_count_); |
+ int frame_slot_count_before = frame_slot_count_; |
+ int slot = AllocateAlignedFrameSlot(width); |
+ stack_slot_count_ += (frame_slot_count_ - frame_slot_count_before); |
+ return slot; |
} |
- int GetOsrStackSlotCount() { return osr_stack_slot_count_; } |
+ int ReserveSpillSlots(size_t slot_count) { |
+ DCHECK_EQ(0, spilled_callee_register_slot_count_); |
+ DCHECK_EQ(0, stack_slot_count_); |
+ stack_slot_count_ += static_cast<int>(slot_count); |
+ frame_slot_count_ += static_cast<int>(slot_count); |
+ return frame_slot_count_ - 1; |
+ } |
- int AllocateSpillSlot(int width) { |
+ private: |
+ int AllocateAlignedFrameSlot(int width) { |
DCHECK(width == 4 || width == 8); |
// Skip one slot if necessary. |
if (width > kPointerSize) { |
DCHECK(width == kPointerSize * 2); |
- spill_slot_count_++; |
- spill_slot_count_ |= 1; |
+ frame_slot_count_++; |
+ frame_slot_count_ |= 1; |
} |
- return spill_slot_count_++; |
- } |
- |
- void ReserveSpillSlots(size_t slot_count) { |
- DCHECK_EQ(0, spill_slot_count_); // can only reserve before allocation. |
- spill_slot_count_ = static_cast<int>(slot_count); |
+ return frame_slot_count_++; |
} |
- void SetPCOnStack(bool val) { pc_on_stack_ = val; } |
- |
- int PCOnStackSize() { return pc_on_stack_ ? kRegisterSize : 0; } |
- |
private: |
- int register_save_area_size_; |
- int spill_slot_count_; |
- int osr_stack_slot_count_; |
+ int frame_slot_count_; |
+ int spilled_callee_register_slot_count_; |
+ int stack_slot_count_; |
BitVector* allocated_registers_; |
BitVector* allocated_double_registers_; |
- bool pc_on_stack_; |
DISALLOW_COPY_AND_ASSIGN(Frame); |
}; |