Commit b6009051 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

ARM: Track Smis on top 4 stack positions and Smi loop variables.

Improve code generation for known smis and suspected Smis.
Review URL: http://codereview.chromium.org/2452002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4783 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5b7e77ac
This diff is collapsed.
...@@ -43,6 +43,7 @@ class RegisterFile; ...@@ -43,6 +43,7 @@ class RegisterFile;
enum InitState { CONST_INIT, NOT_CONST_INIT }; enum InitState { CONST_INIT, NOT_CONST_INIT };
enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
enum GenerateInlineSmi { DONT_GENERATE_INLINE_SMI, GENERATE_INLINE_SMI };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
...@@ -129,24 +130,55 @@ class CodeGenState BASE_EMBEDDED { ...@@ -129,24 +130,55 @@ class CodeGenState BASE_EMBEDDED {
// leaves the code generator with a NULL state. // leaves the code generator with a NULL state.
explicit CodeGenState(CodeGenerator* owner); explicit CodeGenState(CodeGenerator* owner);
// Destroy a code generator state and restore the owning code generator's
// previous state.
virtual ~CodeGenState();
virtual JumpTarget* true_target() const { return NULL; }
virtual JumpTarget* false_target() const { return NULL; }
protected:
inline CodeGenerator* owner() { return owner_; }
inline CodeGenState* previous() const { return previous_; }
private:
CodeGenerator* owner_;
CodeGenState* previous_;
};
class ConditionCodeGenState : public CodeGenState {
public:
// Create a code generator state based on a code generator's current // Create a code generator state based on a code generator's current
// state. The new state has its own pair of branch labels. // state. The new state has its own pair of branch labels.
CodeGenState(CodeGenerator* owner, ConditionCodeGenState(CodeGenerator* owner,
JumpTarget* true_target, JumpTarget* true_target,
JumpTarget* false_target); JumpTarget* false_target);
// Destroy a code generator state and restore the owning code generator's virtual JumpTarget* true_target() const { return true_target_; }
// previous state. virtual JumpTarget* false_target() const { return false_target_; }
~CodeGenState();
JumpTarget* true_target() const { return true_target_; }
JumpTarget* false_target() const { return false_target_; }
private: private:
CodeGenerator* owner_;
JumpTarget* true_target_; JumpTarget* true_target_;
JumpTarget* false_target_; JumpTarget* false_target_;
CodeGenState* previous_; };
class TypeInfoCodeGenState : public CodeGenState {
public:
TypeInfoCodeGenState(CodeGenerator* owner,
Slot* slot_number,
TypeInfo info);
~TypeInfoCodeGenState();
virtual JumpTarget* true_target() const { return previous()->true_target(); }
virtual JumpTarget* false_target() const {
return previous()->false_target();
}
private:
Slot* slot_;
TypeInfo old_type_info_;
}; };
...@@ -216,6 +248,23 @@ class CodeGenerator: public AstVisitor { ...@@ -216,6 +248,23 @@ class CodeGenerator: public AstVisitor {
CodeGenState* state() { return state_; } CodeGenState* state() { return state_; }
void set_state(CodeGenState* state) { state_ = state; } void set_state(CodeGenState* state) { state_ = state; }
TypeInfo type_info(Slot* slot) {
int index = NumberOfSlot(slot);
if (index == kInvalidSlotNumber) return TypeInfo::Unknown();
return (*type_info_)[index];
}
TypeInfo set_type_info(Slot* slot, TypeInfo info) {
int index = NumberOfSlot(slot);
ASSERT(index >= kInvalidSlotNumber);
if (index != kInvalidSlotNumber) {
TypeInfo previous_value = (*type_info_)[index];
(*type_info_)[index] = info;
return previous_value;
}
return TypeInfo::Unknown();
}
void AddDeferred(DeferredCode* code) { deferred_.Add(code); } void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
static const int kUnknownIntValue = -1; static const int kUnknownIntValue = -1;
...@@ -225,7 +274,7 @@ class CodeGenerator: public AstVisitor { ...@@ -225,7 +274,7 @@ class CodeGenerator: public AstVisitor {
static int InlineRuntimeCallArgumentsCount(Handle<String> name); static int InlineRuntimeCallArgumentsCount(Handle<String> name);
// Constants related to patching of inlined load/store. // Constants related to patching of inlined load/store.
static const int kInlinedKeyedLoadInstructionsAfterPatch = 19; static const int kInlinedKeyedLoadInstructionsAfterPatch = 17;
static const int kInlinedKeyedStoreInstructionsAfterPatch = 5; static const int kInlinedKeyedStoreInstructionsAfterPatch = 5;
private: private:
...@@ -239,6 +288,10 @@ class CodeGenerator: public AstVisitor { ...@@ -239,6 +288,10 @@ class CodeGenerator: public AstVisitor {
// Generating deferred code. // Generating deferred code.
void ProcessDeferred(); void ProcessDeferred();
static const int kInvalidSlotNumber = -1;
int NumberOfSlot(Slot* slot);
// State // State
bool has_cc() const { return cc_reg_ != al; } bool has_cc() const { return cc_reg_ != al; }
JumpTarget* true_target() const { return state_->true_target(); } JumpTarget* true_target() const { return state_->true_target(); }
...@@ -351,9 +404,7 @@ class CodeGenerator: public AstVisitor { ...@@ -351,9 +404,7 @@ class CodeGenerator: public AstVisitor {
void GenericBinaryOperation(Token::Value op, void GenericBinaryOperation(Token::Value op,
OverwriteMode overwrite_mode, OverwriteMode overwrite_mode,
int known_rhs = kUnknownIntValue); GenerateInlineSmi inline_smi,
void VirtualFrameBinaryOperation(Token::Value op,
OverwriteMode overwrite_mode,
int known_rhs = kUnknownIntValue); int known_rhs = kUnknownIntValue);
void Comparison(Condition cc, void Comparison(Condition cc,
Expression* left, Expression* left,
...@@ -511,6 +562,8 @@ class CodeGenerator: public AstVisitor { ...@@ -511,6 +562,8 @@ class CodeGenerator: public AstVisitor {
CodeGenState* state_; CodeGenState* state_;
int loop_nesting_; int loop_nesting_;
Vector<TypeInfo>* type_info_;
// Jump targets // Jump targets
BreakTarget function_return_; BreakTarget function_return_;
......
...@@ -50,6 +50,11 @@ void JumpTarget::DoJump() { ...@@ -50,6 +50,11 @@ void JumpTarget::DoJump() {
ASSERT(cgen()->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
if (entry_frame_set_) { if (entry_frame_set_) {
if (entry_label_.is_bound()) {
// If we already bound and generated code at the destination then it
// is too late to ask for less optimistic type assumptions.
ASSERT(entry_frame_.IsCompatibleWith(cgen()->frame()));
}
// There already a frame expectation at the target. // There already a frame expectation at the target.
cgen()->frame()->MergeTo(&entry_frame_); cgen()->frame()->MergeTo(&entry_frame_);
cgen()->DeleteFrame(); cgen()->DeleteFrame();
...@@ -67,8 +72,12 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) { ...@@ -67,8 +72,12 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) {
ASSERT(cgen()->has_valid_frame()); ASSERT(cgen()->has_valid_frame());
if (entry_frame_set_) { if (entry_frame_set_) {
// Backward branch. We have an expected frame to merge to on the if (entry_label_.is_bound()) {
// backward edge. // If we already bound and generated code at the destination then it
// is too late to ask for less optimistic type assumptions.
ASSERT(entry_frame_.IsCompatibleWith(cgen()->frame()));
}
// We have an expected frame to merge to on the backward edge.
cgen()->frame()->MergeTo(&entry_frame_, cc); cgen()->frame()->MergeTo(&entry_frame_, cc);
} else { } else {
// Clone the current frame to use as the expected one at the target. // Clone the current frame to use as the expected one at the target.
......
...@@ -48,6 +48,12 @@ MemOperand VirtualFrame::Receiver() { ...@@ -48,6 +48,12 @@ MemOperand VirtualFrame::Receiver() {
return ParameterAt(-1); return ParameterAt(-1);
} }
void VirtualFrame::Forget(int count) {
SpillAll();
LowerHeight(count);
}
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_VIRTUAL_FRAME_ARM_INL_H_ #endif // V8_VIRTUAL_FRAME_ARM_INL_H_
...@@ -43,7 +43,7 @@ void VirtualFrame::PopToR1R0() { ...@@ -43,7 +43,7 @@ void VirtualFrame::PopToR1R0() {
// Shuffle things around so the top of stack is in r0 and r1. // Shuffle things around so the top of stack is in r0 and r1.
MergeTOSTo(R0_R1_TOS); MergeTOSTo(R0_R1_TOS);
// Pop the two registers off the stack so they are detached from the frame. // Pop the two registers off the stack so they are detached from the frame.
element_count_ -= 2; LowerHeight(2);
top_of_stack_state_ = NO_TOS_REGISTERS; top_of_stack_state_ = NO_TOS_REGISTERS;
} }
...@@ -52,7 +52,7 @@ void VirtualFrame::PopToR1() { ...@@ -52,7 +52,7 @@ void VirtualFrame::PopToR1() {
// Shuffle things around so the top of stack is only in r1. // Shuffle things around so the top of stack is only in r1.
MergeTOSTo(R1_TOS); MergeTOSTo(R1_TOS);
// Pop the register off the stack so it is detached from the frame. // Pop the register off the stack so it is detached from the frame.
element_count_ -= 1; LowerHeight(1);
top_of_stack_state_ = NO_TOS_REGISTERS; top_of_stack_state_ = NO_TOS_REGISTERS;
} }
...@@ -61,13 +61,22 @@ void VirtualFrame::PopToR0() { ...@@ -61,13 +61,22 @@ void VirtualFrame::PopToR0() {
// Shuffle things around so the top of stack only in r0. // Shuffle things around so the top of stack only in r0.
MergeTOSTo(R0_TOS); MergeTOSTo(R0_TOS);
// Pop the register off the stack so it is detached from the frame. // Pop the register off the stack so it is detached from the frame.
element_count_ -= 1; LowerHeight(1);
top_of_stack_state_ = NO_TOS_REGISTERS; top_of_stack_state_ = NO_TOS_REGISTERS;
} }
void VirtualFrame::MergeTo(const VirtualFrame* expected, Condition cond) { void VirtualFrame::MergeTo(const VirtualFrame* expected, Condition cond) {
if (Equals(expected)) return; if (Equals(expected)) return;
ASSERT(expected->IsCompatibleWith(this));
MergeTOSTo(expected->top_of_stack_state_, cond);
ASSERT(register_allocation_map_ == expected->register_allocation_map_);
}
void VirtualFrame::MergeTo(VirtualFrame* expected, Condition cond) {
if (Equals(expected)) return;
expected->tos_known_smi_map_ &= tos_known_smi_map_;
MergeTOSTo(expected->top_of_stack_state_, cond); MergeTOSTo(expected->top_of_stack_state_, cond);
ASSERT(register_allocation_map_ == expected->register_allocation_map_); ASSERT(register_allocation_map_ == expected->register_allocation_map_);
} }
...@@ -420,7 +429,7 @@ void VirtualFrame::Drop(int count) { ...@@ -420,7 +429,7 @@ void VirtualFrame::Drop(int count) {
} }
if (count == 0) return; if (count == 0) return;
__ add(sp, sp, Operand(count * kPointerSize)); __ add(sp, sp, Operand(count * kPointerSize));
element_count_ -= count; LowerHeight(count);
} }
...@@ -430,7 +439,7 @@ void VirtualFrame::Pop() { ...@@ -430,7 +439,7 @@ void VirtualFrame::Pop() {
} else { } else {
top_of_stack_state_ = kStateAfterPop[top_of_stack_state_]; top_of_stack_state_ = kStateAfterPop[top_of_stack_state_];
} }
element_count_--; LowerHeight(1);
} }
...@@ -442,7 +451,7 @@ void VirtualFrame::EmitPop(Register reg) { ...@@ -442,7 +451,7 @@ void VirtualFrame::EmitPop(Register reg) {
__ mov(reg, kTopRegister[top_of_stack_state_]); __ mov(reg, kTopRegister[top_of_stack_state_]);
top_of_stack_state_ = kStateAfterPop[top_of_stack_state_]; top_of_stack_state_ = kStateAfterPop[top_of_stack_state_];
} }
element_count_--; LowerHeight(1);
} }
...@@ -550,7 +559,7 @@ void VirtualFrame::Dup() { ...@@ -550,7 +559,7 @@ void VirtualFrame::Dup() {
UNREACHABLE(); UNREACHABLE();
} }
} }
element_count_++; RaiseHeight(1, tos_known_smi_map_ & 1);
} }
...@@ -589,7 +598,7 @@ void VirtualFrame::Dup2() { ...@@ -589,7 +598,7 @@ void VirtualFrame::Dup2() {
UNREACHABLE(); UNREACHABLE();
} }
} }
element_count_ += 2; RaiseHeight(2, tos_known_smi_map_ & 3);
} }
...@@ -597,7 +606,7 @@ Register VirtualFrame::PopToRegister(Register but_not_to_this_one) { ...@@ -597,7 +606,7 @@ Register VirtualFrame::PopToRegister(Register but_not_to_this_one) {
ASSERT(but_not_to_this_one.is(r0) || ASSERT(but_not_to_this_one.is(r0) ||
but_not_to_this_one.is(r1) || but_not_to_this_one.is(r1) ||
but_not_to_this_one.is(no_reg)); but_not_to_this_one.is(no_reg));
element_count_--; LowerHeight(1);
if (top_of_stack_state_ == NO_TOS_REGISTERS) { if (top_of_stack_state_ == NO_TOS_REGISTERS) {
if (but_not_to_this_one.is(r0)) { if (but_not_to_this_one.is(r0)) {
__ pop(r1); __ pop(r1);
...@@ -625,8 +634,8 @@ void VirtualFrame::EnsureOneFreeTOSRegister() { ...@@ -625,8 +634,8 @@ void VirtualFrame::EnsureOneFreeTOSRegister() {
} }
void VirtualFrame::EmitPush(Register reg) { void VirtualFrame::EmitPush(Register reg, TypeInfo info) {
element_count_++; RaiseHeight(1, info.IsSmi() ? 1 : 0);
if (reg.is(cp)) { if (reg.is(cp)) {
// If we are pushing cp then we are about to make a call and things have to // If we are pushing cp then we are about to make a call and things have to
// be pushed to the physical stack. There's nothing to be gained my moving // be pushed to the physical stack. There's nothing to be gained my moving
...@@ -659,6 +668,9 @@ void VirtualFrame::EmitPush(Register reg) { ...@@ -659,6 +668,9 @@ void VirtualFrame::EmitPush(Register reg) {
void VirtualFrame::SetElementAt(Register reg, int this_far_down) { void VirtualFrame::SetElementAt(Register reg, int this_far_down) {
if (this_far_down < kTOSKnownSmiMapSize) {
tos_known_smi_map_ &= ~(1 << this_far_down);
}
if (this_far_down == 0) { if (this_far_down == 0) {
Pop(); Pop();
Register dest = GetTOSRegister(); Register dest = GetTOSRegister();
...@@ -699,8 +711,8 @@ Register VirtualFrame::GetTOSRegister() { ...@@ -699,8 +711,8 @@ Register VirtualFrame::GetTOSRegister() {
} }
void VirtualFrame::EmitPush(Operand operand) { void VirtualFrame::EmitPush(Operand operand, TypeInfo info) {
element_count_++; RaiseHeight(1, info.IsSmi() ? 1 : 0);
if (SpilledScope::is_spilled()) { if (SpilledScope::is_spilled()) {
__ mov(r0, operand); __ mov(r0, operand);
__ push(r0); __ push(r0);
...@@ -712,8 +724,8 @@ void VirtualFrame::EmitPush(Operand operand) { ...@@ -712,8 +724,8 @@ void VirtualFrame::EmitPush(Operand operand) {
} }
void VirtualFrame::EmitPush(MemOperand operand) { void VirtualFrame::EmitPush(MemOperand operand, TypeInfo info) {
element_count_++; RaiseHeight(1, info.IsSmi() ? 1 : 0);
if (SpilledScope::is_spilled()) { if (SpilledScope::is_spilled()) {
__ ldr(r0, operand); __ ldr(r0, operand);
__ push(r0); __ push(r0);
...@@ -726,7 +738,7 @@ void VirtualFrame::EmitPush(MemOperand operand) { ...@@ -726,7 +738,7 @@ void VirtualFrame::EmitPush(MemOperand operand) {
void VirtualFrame::EmitPushRoot(Heap::RootListIndex index) { void VirtualFrame::EmitPushRoot(Heap::RootListIndex index) {
element_count_++; RaiseHeight(1, 0);
if (SpilledScope::is_spilled()) { if (SpilledScope::is_spilled()) {
__ LoadRoot(r0, index); __ LoadRoot(r0, index);
__ push(r0); __ push(r0);
......
...@@ -154,10 +154,7 @@ class VirtualFrame : public ZoneObject { ...@@ -154,10 +154,7 @@ class VirtualFrame : public ZoneObject {
// Forget elements from the top of the frame to match an actual frame (eg, // Forget elements from the top of the frame to match an actual frame (eg,
// the frame after a runtime call). No code is emitted except to bring the // the frame after a runtime call). No code is emitted except to bring the
// frame to a spilled state. // frame to a spilled state.
void Forget(int count) { void Forget(int count);
SpillAll();
element_count_ -= count;
}
// Spill all values from the frame to memory. // Spill all values from the frame to memory.
void SpillAll(); void SpillAll();
...@@ -184,8 +181,14 @@ class VirtualFrame : public ZoneObject { ...@@ -184,8 +181,14 @@ class VirtualFrame : public ZoneObject {
// Make this virtual frame have a state identical to an expected virtual // Make this virtual frame have a state identical to an expected virtual
// frame. As a side effect, code may be emitted to make this frame match // frame. As a side effect, code may be emitted to make this frame match
// the expected one. // the expected one.
void MergeTo(VirtualFrame* expected, Condition cond = al);
void MergeTo(const VirtualFrame* expected, Condition cond = al); void MergeTo(const VirtualFrame* expected, Condition cond = al);
// Checks whether this frame can be branched to by the other frame.
bool IsCompatibleWith(const VirtualFrame* other) const {
return (tos_known_smi_map_ & (~other->tos_known_smi_map_)) == 0;
}
// Detach a frame from its code generator, perhaps temporarily. This // Detach a frame from its code generator, perhaps temporarily. This
// tells the register allocator that it is free to use frame-internal // tells the register allocator that it is free to use frame-internal
// registers. Used when the code generator's frame is switched from this // registers. Used when the code generator's frame is switched from this
...@@ -234,6 +237,11 @@ class VirtualFrame : public ZoneObject { ...@@ -234,6 +237,11 @@ class VirtualFrame : public ZoneObject {
return MemOperand(sp, adjusted_index * kPointerSize); return MemOperand(sp, adjusted_index * kPointerSize);
} }
bool KnownSmiAt(int index) {
if (index >= kTOSKnownSmiMapSize) return false;
return (tos_known_smi_map_ & (1 << index)) != 0;
}
// A frame-allocated local as an assembly operand. // A frame-allocated local as an assembly operand.
inline MemOperand LocalAt(int index); inline MemOperand LocalAt(int index);
...@@ -352,9 +360,9 @@ class VirtualFrame : public ZoneObject { ...@@ -352,9 +360,9 @@ class VirtualFrame : public ZoneObject {
// Push an element on top of the expression stack and emit a // Push an element on top of the expression stack and emit a
// corresponding push instruction. // corresponding push instruction.
void EmitPush(Register reg); void EmitPush(Register reg, TypeInfo type_info = TypeInfo::Unknown());
void EmitPush(Operand operand); void EmitPush(Operand operand, TypeInfo type_info = TypeInfo::Unknown());
void EmitPush(MemOperand operand); void EmitPush(MemOperand operand, TypeInfo type_info = TypeInfo::Unknown());
void EmitPushRoot(Heap::RootListIndex index); void EmitPushRoot(Heap::RootListIndex index);
// Overwrite the nth thing on the stack. If the nth position is in a // Overwrite the nth thing on the stack. If the nth position is in a
...@@ -419,6 +427,8 @@ class VirtualFrame : public ZoneObject { ...@@ -419,6 +427,8 @@ class VirtualFrame : public ZoneObject {
int element_count_; int element_count_;
TopOfStack top_of_stack_state_:3; TopOfStack top_of_stack_state_:3;
int register_allocation_map_:kNumberOfAllocatedRegisters; int register_allocation_map_:kNumberOfAllocatedRegisters;
static const int kTOSKnownSmiMapSize = 4;
unsigned tos_known_smi_map_:kTOSKnownSmiMapSize;
// The index of the element that is at the processor's stack pointer // The index of the element that is at the processor's stack pointer
// (the sp register). For now since everything is in memory it is given // (the sp register). For now since everything is in memory it is given
...@@ -473,6 +483,25 @@ class VirtualFrame : public ZoneObject { ...@@ -473,6 +483,25 @@ class VirtualFrame : public ZoneObject {
inline bool Equals(const VirtualFrame* other); inline bool Equals(const VirtualFrame* other);
inline void LowerHeight(int count) {
element_count_ -= count;
if (count >= kTOSKnownSmiMapSize) {
tos_known_smi_map_ = 0;
} else {
tos_known_smi_map_ >>= count;
}
}
inline void RaiseHeight(int count, unsigned known_smi_map = 0) {
ASSERT(known_smi_map < (1u << count));
element_count_ += count;
if (count >= kTOSKnownSmiMapSize) {
tos_known_smi_map_ = known_smi_map;
} else {
tos_known_smi_map_ = ((tos_known_smi_map_ << count) | known_smi_map);
}
}
friend class JumpTarget; friend class JumpTarget;
}; };
......
...@@ -318,6 +318,9 @@ Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) { ...@@ -318,6 +318,9 @@ Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) {
Variable* loop_var = init->target()->AsVariableProxy()->AsVariable(); Variable* loop_var = init->target()->AsVariableProxy()->AsVariable();
if (loop_var == NULL || !loop_var->IsStackAllocated()) return NULL; if (loop_var == NULL || !loop_var->IsStackAllocated()) return NULL;
// Don't try to get clever with const or dynamic variables.
if (loop_var->mode() != Variable::VAR) return NULL;
// The initial value has to be a smi. // The initial value has to be a smi.
Literal* init_lit = init->value()->AsLiteral(); Literal* init_lit = init->value()->AsLiteral();
if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL; if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL;
......
...@@ -47,7 +47,7 @@ namespace internal { ...@@ -47,7 +47,7 @@ namespace internal {
class TypeInfo { class TypeInfo {
public: public:
TypeInfo() { } TypeInfo() : type_(kUnknownType) { }
static inline TypeInfo Unknown(); static inline TypeInfo Unknown();
// We know it's a primitive type. // We know it's a primitive type.
......
...@@ -42,7 +42,8 @@ namespace internal { ...@@ -42,7 +42,8 @@ namespace internal {
VirtualFrame::VirtualFrame(InvalidVirtualFrameInitializer* dummy) VirtualFrame::VirtualFrame(InvalidVirtualFrameInitializer* dummy)
: element_count_(0), : element_count_(0),
top_of_stack_state_(NO_TOS_REGISTERS), top_of_stack_state_(NO_TOS_REGISTERS),
register_allocation_map_(0) { } register_allocation_map_(0),
tos_known_smi_map_(0) { }
// On entry to a function, the virtual frame already contains the receiver, // On entry to a function, the virtual frame already contains the receiver,
...@@ -50,20 +51,23 @@ VirtualFrame::VirtualFrame(InvalidVirtualFrameInitializer* dummy) ...@@ -50,20 +51,23 @@ VirtualFrame::VirtualFrame(InvalidVirtualFrameInitializer* dummy)
VirtualFrame::VirtualFrame() VirtualFrame::VirtualFrame()
: element_count_(parameter_count() + 2), : element_count_(parameter_count() + 2),
top_of_stack_state_(NO_TOS_REGISTERS), top_of_stack_state_(NO_TOS_REGISTERS),
register_allocation_map_(0) { } register_allocation_map_(0),
tos_known_smi_map_(0) { }
// When cloned, a frame is a deep copy of the original. // When cloned, a frame is a deep copy of the original.
VirtualFrame::VirtualFrame(VirtualFrame* original) VirtualFrame::VirtualFrame(VirtualFrame* original)
: element_count_(original->element_count()), : element_count_(original->element_count()),
top_of_stack_state_(original->top_of_stack_state_), top_of_stack_state_(original->top_of_stack_state_),
register_allocation_map_(original->register_allocation_map_) { } register_allocation_map_(original->register_allocation_map_),
tos_known_smi_map_(0) { }
bool VirtualFrame::Equals(const VirtualFrame* other) { bool VirtualFrame::Equals(const VirtualFrame* other) {
ASSERT(element_count() == other->element_count()); ASSERT(element_count() == other->element_count());
if (top_of_stack_state_ != other->top_of_stack_state_) return false; if (top_of_stack_state_ != other->top_of_stack_state_) return false;
if (register_allocation_map_ != other->register_allocation_map_) return false; if (register_allocation_map_ != other->register_allocation_map_) return false;
if (tos_known_smi_map_ != other->tos_known_smi_map_) return false;
return true; return true;
} }
......
...@@ -36,7 +36,7 @@ namespace internal { ...@@ -36,7 +36,7 @@ namespace internal {
void VirtualFrame::Adjust(int count) { void VirtualFrame::Adjust(int count) {
ASSERT(count >= 0); ASSERT(count >= 0);
element_count_ += count; RaiseHeight(count, 0);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment