diff options
Diffstat (limited to 'deps/v8/src/x64/virtual-frame-x64.h')
-rw-r--r-- | deps/v8/src/x64/virtual-frame-x64.h | 203 |
1 files changed, 133 insertions, 70 deletions
diff --git a/deps/v8/src/x64/virtual-frame-x64.h b/deps/v8/src/x64/virtual-frame-x64.h index f71766d033..d341a1eee4 100644 --- a/deps/v8/src/x64/virtual-frame-x64.h +++ b/deps/v8/src/x64/virtual-frame-x64.h @@ -29,8 +29,10 @@ #define V8_X64_VIRTUAL_FRAME_X64_H_ #include "register-allocator.h" +#include "scopes.h" -namespace v8 { namespace internal { +namespace v8 { +namespace internal { // ------------------------------------------------------------------------- // Virtual frames @@ -41,7 +43,7 @@ namespace v8 { namespace internal { // as random access to the expression stack elements, locals, and // parameters. -class VirtualFrame : public Malloced { +class VirtualFrame : public ZoneObject { public: // A utility class to introduce a scope where the virtual frame is // expected to remain spilled. The constructor spills the code @@ -50,42 +52,66 @@ class VirtualFrame : public Malloced { // generator is being transformed. class SpilledScope BASE_EMBEDDED { public: - explicit SpilledScope(CodeGenerator* cgen); + SpilledScope() : previous_state_(cgen()->in_spilled_code()) { + ASSERT(cgen()->has_valid_frame()); + cgen()->frame()->SpillAll(); + cgen()->set_in_spilled_code(true); + } - ~SpilledScope(); + ~SpilledScope() { + cgen()->set_in_spilled_code(previous_state_); + } private: - CodeGenerator* cgen_; bool previous_state_; + + CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } }; // An illegal index into the virtual frame. static const int kIllegalIndex = -1; // Construct an initial virtual frame on entry to a JS function. - explicit VirtualFrame(CodeGenerator* cgen); + VirtualFrame(); // Construct a virtual frame as a clone of an existing one. explicit VirtualFrame(VirtualFrame* original); + CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } + MacroAssembler* masm() { return cgen()->masm(); } + // Create a duplicate of an existing valid frame element. FrameElement CopyElementAt(int index); + // The number of elements on the virtual frame. + int element_count() { return elements_.length(); } + // The height of the virtual expression stack. - int height() const { - return elements_.length() - expression_base_index(); + int height() { + return element_count() - expression_base_index(); + } + + int register_location(int num) { + ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); + return register_locations_[num]; } - int register_index(Register reg) { - return register_locations_[reg.code()]; + int register_location(Register reg) { + return register_locations_[RegisterAllocator::ToNumber(reg)]; } - bool is_used(int reg_code) { - return register_locations_[reg_code] != kIllegalIndex; + void set_register_location(Register reg, int index) { + register_locations_[RegisterAllocator::ToNumber(reg)] = index; + } + + bool is_used(int num) { + ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters); + return register_locations_[num] != kIllegalIndex; } bool is_used(Register reg) { - return is_used(reg.code()); + return register_locations_[RegisterAllocator::ToNumber(reg)] + != kIllegalIndex; } // Add extra in-memory elements to the top of the frame to match an actual @@ -98,7 +124,12 @@ class VirtualFrame : public Malloced { // match an external frame effect (examples include a call removing // its arguments, and exiting a try/catch removing an exception // handler). No code will be emitted. - void Forget(int count); + void Forget(int count) { + ASSERT(count >= 0); + ASSERT(stack_pointer_ == element_count() - 1); + stack_pointer_ -= count; + ForgetElements(count); + } // Forget count elements from the top of the frame without adjusting // the stack pointer downward. This is used, for example, before @@ -109,13 +140,25 @@ class VirtualFrame : public Malloced { void SpillAll(); // Spill all occurrences of a specific register from the frame. - void Spill(Register reg); + void Spill(Register reg) { + if (is_used(reg)) SpillElementAt(register_location(reg)); + } // Spill all occurrences of an arbitrary register if possible. Return the // register spilled or no_reg if it was not possible to free any register // (ie, they all have frame-external references). Register SpillAnyRegister(); + // Sync the range of elements in [begin, end] with memory. + void SyncRange(int begin, int end); + + // Make this frame so that an arbitrary frame of the same height can + // be merged to it. Copies and constants are removed from the + // topmost mergable_elements elements of the frame. A + // mergable_elements of JumpTarget::kAllElements indicates constants + // and copies are should be removed from the entire frame. + void MakeMergable(int mergable_elements); + // Prepare this virtual frame for merging to an expected frame by // performing some state changes that do not require generating // code. It is guaranteed that no code will be generated. @@ -130,13 +173,23 @@ class VirtualFrame : public Malloced { // tells the register allocator that it is free to use frame-internal // registers. Used when the code generator's frame is switched from this // one to NULL by an unconditional jump. - void DetachFromCodeGenerator(); + void DetachFromCodeGenerator() { + RegisterAllocator* cgen_allocator = cgen()->allocator(); + for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { + if (is_used(i)) cgen_allocator->Unuse(i); + } + } // (Re)attach a frame to its code generator. This informs the register // allocator that the frame-internal register references are active again. // Used when a code generator's frame is switched from NULL to this one by // binding a label. - void AttachToCodeGenerator(); + void AttachToCodeGenerator() { + RegisterAllocator* cgen_allocator = cgen()->allocator(); + for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { + if (is_used(i)) cgen_allocator->Use(i); + } + } // Emit code for the physical JS entry and exit frame sequences. After // calling Enter, the virtual frame is ready for use; and after calling @@ -151,7 +204,7 @@ class VirtualFrame : public Malloced { void PrepareForReturn(); // Allocate and initialize the frame-allocated locals. - void AllocateStackSlots(int count); + void AllocateStackSlots(); // An element of the expression stack as an assembly operand. Operand ElementAt(int index) const { @@ -164,22 +217,22 @@ class VirtualFrame : public Malloced { // Set a frame element to a constant. The index is frame-top relative. void SetElementAt(int index, Handle<Object> value) { - Result temp(value, cgen_); + Result temp(value); SetElementAt(index, &temp); } void PushElementAt(int index) { - PushFrameSlotAt(elements_.length() - index - 1); + PushFrameSlotAt(element_count() - index - 1); } void StoreToElementAt(int index) { - StoreToFrameSlotAt(elements_.length() - index - 1); + StoreToFrameSlotAt(element_count() - index - 1); } // A frame-allocated local as an assembly operand. - Operand LocalAt(int index) const { + Operand LocalAt(int index) { ASSERT(0 <= index); - ASSERT(index < local_count_); + ASSERT(index < local_count()); return Operand(rbp, kLocal0Offset - index * kPointerSize); } @@ -215,10 +268,10 @@ class VirtualFrame : public Malloced { void RestoreContextRegister(); // A parameter as an assembly operand. - Operand ParameterAt(int index) const { + Operand ParameterAt(int index) { ASSERT(-1 <= index); // -1 is the receiver. - ASSERT(index < parameter_count_); - return Operand(rbp, (1 + parameter_count_ - index) * kPointerSize); + ASSERT(index < parameter_count()); + return Operand(rbp, (1 + parameter_count() - index) * kPointerSize); } // Push a copy of the value of a parameter frame slot on top of the frame. @@ -240,14 +293,17 @@ class VirtualFrame : public Malloced { } // The receiver frame slot. - Operand Receiver() const { return ParameterAt(-1); } + Operand Receiver() { return ParameterAt(-1); } // Push a try-catch or try-finally handler on top of the virtual frame. void PushTryHandler(HandlerType type); // Call stub given the number of arguments it expects on (and // removes from) the stack. - Result CallStub(CodeStub* stub, int arg_count); + Result CallStub(CodeStub* stub, int arg_count) { + PrepareForCall(arg_count, arg_count); + return RawCallStub(stub); + } // Call stub that takes a single argument passed in eax. The // argument is given as a result which does not have to be eax or @@ -307,7 +363,7 @@ class VirtualFrame : public Malloced { void Drop() { Drop(1); } // Duplicate the top element of the frame. - void Dup() { PushFrameSlotAt(elements_.length() - 1); } + void Dup() { PushFrameSlotAt(element_count() - 1); } // Pop an element from the top of the expression stack. Returns a // Result, which may be a constant or a register. @@ -331,7 +387,15 @@ class VirtualFrame : public Malloced { // Pushing a result invalidates it (its contents become owned by the // frame). - void Push(Result* result); + void Push(Result* result) { + if (result->is_register()) { + Push(result->reg(), result->static_type()); + } else { + ASSERT(result->is_constant()); + Push(result->handle()); + } + result->Unuse(); + } // Nip removes zero or more elements from immediately below the top // of the frame, leaving the previous top-of-frame value on top of @@ -346,70 +410,69 @@ class VirtualFrame : public Malloced { static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize; static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots. - CodeGenerator* cgen_; - MacroAssembler* masm_; - - List<FrameElement> elements_; - - // The number of frame-allocated locals and parameters respectively. - int parameter_count_; - int local_count_; + ZoneList<FrameElement> elements_; // The index of the element that is at the processor's stack pointer // (the esp register). int stack_pointer_; - // The index of the element that is at the processor's frame pointer - // (the ebp register). - int frame_pointer_; - // The index of the register frame element using each register, or // kIllegalIndex if a register is not on the frame. - int register_locations_[kNumRegisters]; + int register_locations_[RegisterAllocator::kNumRegisters]; + + // The number of frame-allocated locals and parameters respectively. + int parameter_count() { return cgen()->scope()->num_parameters(); } + int local_count() { return cgen()->scope()->num_stack_slots(); } + + // The index of the element that is at the processor's frame pointer + // (the ebp register). The parameters, receiver, and return address + // are below the frame pointer. + int frame_pointer() { return parameter_count() + 2; } // The index of the first parameter. The receiver lies below the first // parameter. - int param0_index() const { return 1; } + int param0_index() { return 1; } - // The index of the context slot in the frame. - int context_index() const { - ASSERT(frame_pointer_ != kIllegalIndex); - return frame_pointer_ + 1; - } + // The index of the context slot in the frame. It is immediately + // above the frame pointer. + int context_index() { return frame_pointer() + 1; } - // The index of the function slot in the frame. It lies above the context - // slot. - int function_index() const { - ASSERT(frame_pointer_ != kIllegalIndex); - return frame_pointer_ + 2; - } + // The index of the function slot in the frame. It is above the frame + // pointer and the context slot. + int function_index() { return frame_pointer() + 2; } - // The index of the first local. Between the parameters and the locals - // lie the return address, the saved frame pointer, the context, and the - // function. - int local0_index() const { - ASSERT(frame_pointer_ != kIllegalIndex); - return frame_pointer_ + 3; - } + // The index of the first local. Between the frame pointer and the + // locals lie the context and the function. + int local0_index() { return frame_pointer() + 3; } // The index of the base of the expression stack. - int expression_base_index() const { return local0_index() + local_count_; } + int expression_base_index() { return local0_index() + local_count(); } // Convert a frame index into a frame pointer relative offset into the // actual stack. - int fp_relative(int index) const { - return (frame_pointer_ - index) * kPointerSize; + int fp_relative(int index) { + ASSERT(index < element_count()); + ASSERT(frame_pointer() < element_count()); // FP is on the frame. + return (frame_pointer() - index) * kPointerSize; } // Record an occurrence of a register in the virtual frame. This has the // effect of incrementing the register's external reference count and // of updating the index of the register's location in the frame. - void Use(Register reg, int index); + void Use(Register reg, int index) { + ASSERT(!is_used(reg)); + set_register_location(reg, index); + cgen()->allocator()->Use(reg); + } // Record that a register reference has been dropped from the frame. This // decrements the register's external reference count and invalidates the // index of the register's location in the frame. - void Unuse(Register reg); + void Unuse(Register reg) { + ASSERT(is_used(reg)); + set_register_location(reg, kIllegalIndex); + cgen()->allocator()->Unuse(reg); + } // Spill the element at a particular index---write it to memory if // necessary, free any associated register, and forget its value if @@ -421,9 +484,6 @@ class VirtualFrame : public Malloced { // Keep the element type as register or constant, and clear the dirty bit. void SyncElementAt(int index); - // Sync the range of elements in [begin, end). - void SyncRange(int begin, int end); - // Sync a single unsynced element that lies beneath or at the stack pointer. void SyncElementBelowStackPointer(int index); @@ -485,9 +545,12 @@ class VirtualFrame : public Malloced { bool Equals(VirtualFrame* other); + // Classes that need raw access to the elements_ array. + friend class DeferredCode; friend class JumpTarget; }; + } } // namespace v8::internal #endif // V8_X64_VIRTUAL_FRAME_X64_H_ |