// generator is being transformed.
class SpilledScope BASE_EMBEDDED {
public:
- explicit SpilledScope(CodeGenerator* cgen);
+ explicit SpilledScope(CodeGenerator* cgen)
+ : cgen_(cgen),
+ 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_;
// Forget elements from the top of the frame to match an actual frame (eg,
// the frame after a runtime call). No code is emitted.
- void Forget(int count);
+ void Forget(int count) {
+ ASSERT(count >= 0);
+ ASSERT(stack_pointer_ == elements_.length() - 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
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_index(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
// 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 expects its argument in r0. The argument is given
// as a result which must be the register r0.
void Push(Smi* value) { Push(Handle<Object>(value)); }
// 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
// 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));
+ register_locations_[reg.code()] = 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(register_locations_[reg.code()] != kIllegalIndex);
+ register_locations_[reg.code()] = 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
// generator is being transformed.
class SpilledScope BASE_EMBEDDED {
public:
- explicit SpilledScope(CodeGenerator* cgen);
+ explicit SpilledScope(CodeGenerator* cgen)
+ : cgen_(cgen),
+ 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_;
// 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_ == elements_.length() - 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
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_index(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
// 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
// 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
// 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));
+ register_locations_[reg.code()] = 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(register_locations_[reg.code()] != kIllegalIndex);
+ register_locations_[reg.code()] = 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
// -------------------------------------------------------------------------
// VirtualFrame implementation.
-VirtualFrame::SpilledScope::SpilledScope(CodeGenerator* cgen)
- : cgen_(cgen),
- previous_state_(cgen->in_spilled_code()) {
- ASSERT(cgen->has_valid_frame());
- cgen->frame()->SpillAll();
- cgen->set_in_spilled_code(true);
-}
-
-
-VirtualFrame::SpilledScope::~SpilledScope() {
- cgen_->set_in_spilled_code(previous_state_);
-}
-
-
// When cloned, a frame is a deep copy of the original.
VirtualFrame::VirtualFrame(VirtualFrame* original)
: cgen_(original->cgen_),
}
-// Modify the state of the virtual frame to match the actual frame by
-// removing elements from the top of the virtual frame. The elements will
-// be externally popped from the actual frame (eg, by a runtime call). No
-// code is emitted.
-void VirtualFrame::Forget(int count) {
- ASSERT(count >= 0);
- ASSERT(stack_pointer_ == elements_.length() - 1);
-
- stack_pointer_ -= count;
- ForgetElements(count);
-}
-
-
void VirtualFrame::ForgetElements(int count) {
ASSERT(count >= 0);
ASSERT(elements_.length() >= count);
}
-void VirtualFrame::Use(Register reg, int index) {
- ASSERT(register_locations_[reg.code()] == kIllegalIndex);
- register_locations_[reg.code()] = index;
- cgen_->allocator()->Use(reg);
-}
-
-
-void VirtualFrame::Unuse(Register reg) {
- ASSERT(register_locations_[reg.code()] != kIllegalIndex);
- register_locations_[reg.code()] = kIllegalIndex;
- cgen_->allocator()->Unuse(reg);
-}
-
-
-void VirtualFrame::Spill(Register target) {
- if (is_used(target)) {
- SpillElementAt(register_index(target));
- }
-}
-
-
// If there are any registers referenced only by the frame, spill one.
Register VirtualFrame::SpillAnyRegister() {
// Find the leftmost (ordered by register code) register whose only
void VirtualFrame::PushFrameSlotAt(int index) {
- FrameElement new_element = CopyElementAt(index);
- elements_.Add(new_element);
-}
-
-
-Result VirtualFrame::CallStub(CodeStub* stub, int arg_count) {
- PrepareForCall(arg_count, arg_count);
- return RawCallStub(stub);
+ elements_.Add(CopyElementAt(index));
}
}
-void VirtualFrame::Push(Result* result) {
- if (result->is_register()) {
- Push(result->reg(), result->static_type());
- } else {
- ASSERT(result->is_constant());
- Push(result->handle());
- }
- result->Unuse();
-}
-
-
void VirtualFrame::Nip(int num_dropped) {
ASSERT(num_dropped >= 0);
if (num_dropped == 0) return;
// 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
// generator is being transformed.
class SpilledScope BASE_EMBEDDED {
public:
- explicit SpilledScope(CodeGenerator* cgen);
+ explicit SpilledScope(CodeGenerator* cgen)
+ : cgen_(cgen),
+ 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_;
// 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_ == elements_.length() - 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
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_index(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();
+ // 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.
}
}
}
+
// (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
// 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
// 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
CodeGenerator* cgen_;
MacroAssembler* masm_;
- List<FrameElement> elements_;
+ ZoneList<FrameElement> elements_;
// The number of frame-allocated locals and parameters respectively.
- int parameter_count_;
- int local_count_;
+ int16_t parameter_count_;
+ int16_t local_count_;
// The index of the element that is at the processor's stack pointer
// (the esp register).
- int stack_pointer_;
+ int16_t stack_pointer_;
// The index of the element that is at the processor's frame pointer
// (the ebp register).
- int frame_pointer_;
+ int16_t 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];
+ int16_t register_locations_[kNumRegisters];
// The index of the first parameter. The receiver lies below the first
// parameter.
// 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));
+ register_locations_[reg.code()] = 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(register_locations_[reg.code()] != kIllegalIndex);
+ register_locations_[reg.code()] = 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