Commit ef85ba46 authored by ager@chromium.org's avatar ager@chromium.org

First round of size reduction for JumpTargets. Reduce their size by

two words: there is no reason to keep a pointer to the current code
generator and macro assembler in the JumpTarget.
Review URL: http://codereview.chromium.org/113458

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1987 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 13a96b3a
...@@ -136,7 +136,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -136,7 +136,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
frame_->AllocateStackSlots(scope_->num_stack_slots()); frame_->AllocateStackSlots(scope_->num_stack_slots());
// Initialize the function return target after the locals are set // Initialize the function return target after the locals are set
// up, because it needs the expected frame height from the frame. // up, because it needs the expected frame height from the frame.
function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL); function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
function_return_is_shadowed_ = false; function_return_is_shadowed_ = false;
VirtualFrame::SpilledScope spilled_scope(this); VirtualFrame::SpilledScope spilled_scope(this);
...@@ -456,14 +456,14 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { ...@@ -456,14 +456,14 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
int original_height = frame_->height(); int original_height = frame_->height();
#endif #endif
ASSERT(!in_spilled_code()); ASSERT(!in_spilled_code());
JumpTarget true_target(this); JumpTarget true_target;
JumpTarget false_target(this); JumpTarget false_target;
LoadCondition(x, typeof_state, &true_target, &false_target, false); LoadCondition(x, typeof_state, &true_target, &false_target, false);
if (has_cc()) { if (has_cc()) {
// Convert cc_reg_ into a boolean value. // Convert cc_reg_ into a boolean value.
JumpTarget loaded(this); JumpTarget loaded;
JumpTarget materialize_true(this); JumpTarget materialize_true;
materialize_true.Branch(cc_reg_); materialize_true.Branch(cc_reg_);
__ mov(r0, Operand(Factory::false_value())); __ mov(r0, Operand(Factory::false_value()));
frame_->EmitPush(r0); frame_->EmitPush(r0);
...@@ -478,7 +478,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { ...@@ -478,7 +478,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
if (true_target.is_linked() || false_target.is_linked()) { if (true_target.is_linked() || false_target.is_linked()) {
// We have at least one condition value that has been "translated" // We have at least one condition value that has been "translated"
// into a branch, thus it needs to be loaded explicitly. // into a branch, thus it needs to be loaded explicitly.
JumpTarget loaded(this); JumpTarget loaded;
if (frame_ != NULL) { if (frame_ != NULL) {
loaded.Jump(); // Don't lose the current TOS. loaded.Jump(); // Don't lose the current TOS.
} }
...@@ -865,7 +865,7 @@ void CodeGenerator::SmiOperation(Token::Value op, ...@@ -865,7 +865,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
int int_value = Smi::cast(*value)->value(); int int_value = Smi::cast(*value)->value();
JumpTarget exit(this); JumpTarget exit;
frame_->EmitPop(r0); frame_->EmitPop(r0);
switch (op) { switch (op) {
...@@ -995,8 +995,8 @@ void CodeGenerator::Comparison(Condition cc, bool strict) { ...@@ -995,8 +995,8 @@ void CodeGenerator::Comparison(Condition cc, bool strict) {
// Strict only makes sense for equality comparisons. // Strict only makes sense for equality comparisons.
ASSERT(!strict || cc == eq); ASSERT(!strict || cc == eq);
JumpTarget exit(this); JumpTarget exit;
JumpTarget smi(this); JumpTarget smi;
// Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
if (cc == gt || cc == le) { if (cc == gt || cc == le) {
cc = ReverseCondition(cc); cc = ReverseCondition(cc);
...@@ -1156,7 +1156,7 @@ void CodeGenerator::VisitBlock(Block* node) { ...@@ -1156,7 +1156,7 @@ void CodeGenerator::VisitBlock(Block* node) {
VirtualFrame::SpilledScope spilled_scope(this); VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Block"); Comment cmnt(masm_, "[ Block");
CodeForStatementPosition(node); CodeForStatementPosition(node);
node->break_target()->Initialize(this); node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
VisitStatementsAndSpill(node->statements()); VisitStatementsAndSpill(node->statements());
if (node->break_target()->is_linked()) { if (node->break_target()->is_linked()) {
node->break_target()->Bind(); node->break_target()->Bind();
...@@ -1290,11 +1290,11 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) { ...@@ -1290,11 +1290,11 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
CodeForStatementPosition(node); CodeForStatementPosition(node);
JumpTarget exit(this); JumpTarget exit;
if (has_then_stm && has_else_stm) { if (has_then_stm && has_else_stm) {
Comment cmnt(masm_, "[ IfThenElse"); Comment cmnt(masm_, "[ IfThenElse");
JumpTarget then(this); JumpTarget then;
JumpTarget else_(this); JumpTarget else_;
// if (cond) // if (cond)
LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
&then, &else_, true); &then, &else_, true);
...@@ -1318,7 +1318,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) { ...@@ -1318,7 +1318,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
} else if (has_then_stm) { } else if (has_then_stm) {
Comment cmnt(masm_, "[ IfThen"); Comment cmnt(masm_, "[ IfThen");
ASSERT(!has_else_stm); ASSERT(!has_else_stm);
JumpTarget then(this); JumpTarget then;
// if (cond) // if (cond)
LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
&then, &exit, true); &then, &exit, true);
...@@ -1334,7 +1334,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) { ...@@ -1334,7 +1334,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
} else if (has_else_stm) { } else if (has_else_stm) {
Comment cmnt(masm_, "[ IfElse"); Comment cmnt(masm_, "[ IfElse");
ASSERT(!has_then_stm); ASSERT(!has_then_stm);
JumpTarget else_(this); JumpTarget else_;
// if (!cond) // if (!cond)
LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
&exit, &else_, true); &exit, &else_, true);
...@@ -1424,7 +1424,7 @@ void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { ...@@ -1424,7 +1424,7 @@ void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) {
frame_->CallRuntime(Runtime::kPushContext, 1); frame_->CallRuntime(Runtime::kPushContext, 1);
} }
#ifdef DEBUG #ifdef DEBUG
JumpTarget verified_true(this); JumpTarget verified_true;
__ cmp(r0, Operand(cp)); __ cmp(r0, Operand(cp));
verified_true.Branch(eq); verified_true.Branch(eq);
__ stop("PushContext: r0 is expected to be the same as cp"); __ stop("PushContext: r0 is expected to be the same as cp");
...@@ -1468,8 +1468,8 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable( ...@@ -1468,8 +1468,8 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
Vector<Label*> case_targets, Vector<Label*> case_targets,
Vector<Label> case_labels) { Vector<Label> case_labels) {
VirtualFrame::SpilledScope spilled_scope(this); VirtualFrame::SpilledScope spilled_scope(this);
JumpTarget setup_default(this); JumpTarget setup_default;
JumpTarget is_smi(this); JumpTarget is_smi;
// A non-null default label pointer indicates a default case among // A non-null default label pointer indicates a default case among
// the case labels. Otherwise we use the break target as a // the case labels. Otherwise we use the break target as a
...@@ -1539,7 +1539,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { ...@@ -1539,7 +1539,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
VirtualFrame::SpilledScope spilled_scope(this); VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ SwitchStatement"); Comment cmnt(masm_, "[ SwitchStatement");
CodeForStatementPosition(node); CodeForStatementPosition(node);
node->break_target()->Initialize(this); node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
LoadAndSpill(node->tag()); LoadAndSpill(node->tag());
if (TryGenerateFastCaseSwitchStatement(node)) { if (TryGenerateFastCaseSwitchStatement(node)) {
...@@ -1547,10 +1547,10 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { ...@@ -1547,10 +1547,10 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
return; return;
} }
JumpTarget next_test(this); JumpTarget next_test;
JumpTarget fall_through(this); JumpTarget fall_through;
JumpTarget default_entry(this); JumpTarget default_entry;
JumpTarget default_exit(this, JumpTarget::BIDIRECTIONAL); JumpTarget default_exit(JumpTarget::BIDIRECTIONAL);
ZoneList<CaseClause*>* cases = node->cases(); ZoneList<CaseClause*>* cases = node->cases();
int length = cases->length(); int length = cases->length();
CaseClause* default_clause = NULL; CaseClause* default_clause = NULL;
...@@ -1633,7 +1633,7 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -1633,7 +1633,7 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
VirtualFrame::SpilledScope spilled_scope(this); VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ LoopStatement"); Comment cmnt(masm_, "[ LoopStatement");
CodeForStatementPosition(node); CodeForStatementPosition(node);
node->break_target()->Initialize(this); node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
// Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
// known result for the test expression, with no side effects. // known result for the test expression, with no side effects.
...@@ -1654,19 +1654,19 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -1654,19 +1654,19 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
switch (node->type()) { switch (node->type()) {
case LoopStatement::DO_LOOP: { case LoopStatement::DO_LOOP: {
JumpTarget body(this, JumpTarget::BIDIRECTIONAL); JumpTarget body(JumpTarget::BIDIRECTIONAL);
// Label the top of the loop for the backward CFG edge. If the test // Label the top of the loop for the backward CFG edge. If the test
// is always true we can use the continue target, and if the test is // is always true we can use the continue target, and if the test is
// always false there is no need. // always false there is no need.
if (info == ALWAYS_TRUE) { if (info == ALWAYS_TRUE) {
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind(); node->continue_target()->Bind();
} else if (info == ALWAYS_FALSE) { } else if (info == ALWAYS_FALSE) {
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
} else { } else {
ASSERT(info == DONT_KNOW); ASSERT(info == DONT_KNOW);
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
body.Bind(); body.Bind();
} }
...@@ -1713,11 +1713,11 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -1713,11 +1713,11 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
// Label the top of the loop with the continue target for the backward // Label the top of the loop with the continue target for the backward
// CFG edge. // CFG edge.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind(); node->continue_target()->Bind();
if (info == DONT_KNOW) { if (info == DONT_KNOW) {
JumpTarget body(this); JumpTarget body;
LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
&body, node->break_target(), true); &body, node->break_target(), true);
if (has_valid_frame()) { if (has_valid_frame()) {
...@@ -1743,7 +1743,7 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -1743,7 +1743,7 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
} }
case LoopStatement::FOR_LOOP: { case LoopStatement::FOR_LOOP: {
JumpTarget loop(this, JumpTarget::BIDIRECTIONAL); JumpTarget loop(JumpTarget::BIDIRECTIONAL);
if (node->init() != NULL) { if (node->init() != NULL) {
VisitAndSpill(node->init()); VisitAndSpill(node->init());
...@@ -1755,16 +1755,16 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -1755,16 +1755,16 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
// If there is no update statement, label the top of the loop with the // If there is no update statement, label the top of the loop with the
// continue target, otherwise with the loop target. // continue target, otherwise with the loop target.
if (node->next() == NULL) { if (node->next() == NULL) {
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind(); node->continue_target()->Bind();
} else { } else {
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
loop.Bind(); loop.Bind();
} }
// If the test is always true, there is no need to compile it. // If the test is always true, there is no need to compile it.
if (info == DONT_KNOW) { if (info == DONT_KNOW) {
JumpTarget body(this); JumpTarget body;
LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF, LoadConditionAndSpill(node->cond(), NOT_INSIDE_TYPEOF,
&body, node->break_target(), true); &body, node->break_target(), true);
if (has_valid_frame()) { if (has_valid_frame()) {
...@@ -1824,12 +1824,12 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -1824,12 +1824,12 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
Comment cmnt(masm_, "[ ForInStatement"); Comment cmnt(masm_, "[ ForInStatement");
CodeForStatementPosition(node); CodeForStatementPosition(node);
JumpTarget primitive(this); JumpTarget primitive;
JumpTarget jsobject(this); JumpTarget jsobject;
JumpTarget fixed_array(this); JumpTarget fixed_array;
JumpTarget entry(this, JumpTarget::BIDIRECTIONAL); JumpTarget entry(JumpTarget::BIDIRECTIONAL);
JumpTarget end_del_check(this); JumpTarget end_del_check;
JumpTarget exit(this); JumpTarget exit;
// Get the object to enumerate over (converted to JSObject). // Get the object to enumerate over (converted to JSObject).
LoadAndSpill(node->enumerable()); LoadAndSpill(node->enumerable());
...@@ -1914,8 +1914,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -1914,8 +1914,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
// sp[4] : enumerable // sp[4] : enumerable
// Grab the current frame's height for the break and continue // Grab the current frame's height for the break and continue
// targets only after all the state is pushed on the frame. // targets only after all the state is pushed on the frame.
node->break_target()->Initialize(this); node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
__ ldr(r0, frame_->ElementAt(0)); // load the current count __ ldr(r0, frame_->ElementAt(0)); // load the current count
__ ldr(r1, frame_->ElementAt(1)); // load the length __ ldr(r1, frame_->ElementAt(1)); // load the length
...@@ -2018,8 +2018,8 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) { ...@@ -2018,8 +2018,8 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
Comment cmnt(masm_, "[ TryCatch"); Comment cmnt(masm_, "[ TryCatch");
CodeForStatementPosition(node); CodeForStatementPosition(node);
JumpTarget try_block(this); JumpTarget try_block;
JumpTarget exit(this); JumpTarget exit;
try_block.Call(); try_block.Call();
// --- Catch block --- // --- Catch block ---
...@@ -2150,8 +2150,8 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -2150,8 +2150,8 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// break/continue from within the try block. // break/continue from within the try block.
enum { FALLING, THROWING, JUMPING }; enum { FALLING, THROWING, JUMPING };
JumpTarget try_block(this); JumpTarget try_block;
JumpTarget finally_block(this); JumpTarget finally_block;
try_block.Call(); try_block.Call();
...@@ -2296,7 +2296,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -2296,7 +2296,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
JumpTarget* original = shadows[i]->other_target(); JumpTarget* original = shadows[i]->other_target();
__ cmp(r2, Operand(Smi::FromInt(JUMPING + i))); __ cmp(r2, Operand(Smi::FromInt(JUMPING + i)));
if (!function_return_is_shadowed_ && i == kReturnShadowIndex) { if (!function_return_is_shadowed_ && i == kReturnShadowIndex) {
JumpTarget skip(this); JumpTarget skip;
skip.Branch(ne); skip.Branch(ne);
frame_->PrepareForReturn(); frame_->PrepareForReturn();
original->Jump(); original->Jump();
...@@ -2309,7 +2309,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -2309,7 +2309,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
if (has_valid_frame()) { if (has_valid_frame()) {
// Check if we need to rethrow the exception. // Check if we need to rethrow the exception.
JumpTarget exit(this); JumpTarget exit;
__ cmp(r2, Operand(Smi::FromInt(THROWING))); __ cmp(r2, Operand(Smi::FromInt(THROWING)));
exit.Branch(ne); exit.Branch(ne);
...@@ -2391,9 +2391,9 @@ void CodeGenerator::VisitConditional(Conditional* node) { ...@@ -2391,9 +2391,9 @@ void CodeGenerator::VisitConditional(Conditional* node) {
#endif #endif
VirtualFrame::SpilledScope spilled_scope(this); VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Conditional"); Comment cmnt(masm_, "[ Conditional");
JumpTarget then(this); JumpTarget then;
JumpTarget else_(this); JumpTarget else_;
JumpTarget exit(this); JumpTarget exit;
LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF, LoadConditionAndSpill(node->condition(), NOT_INSIDE_TYPEOF,
&then, &else_, true); &then, &else_, true);
Branch(false, &else_); Branch(false, &else_);
...@@ -2412,8 +2412,8 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -2412,8 +2412,8 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
if (slot->type() == Slot::LOOKUP) { if (slot->type() == Slot::LOOKUP) {
ASSERT(slot->var()->is_dynamic()); ASSERT(slot->var()->is_dynamic());
JumpTarget slow(this); JumpTarget slow;
JumpTarget done(this); JumpTarget done;
// Generate fast-case code for variables that might be shadowed by // Generate fast-case code for variables that might be shadowed by
// eval-introduced variables. Eval is used a lot without // eval-introduced variables. Eval is used a lot without
...@@ -2620,7 +2620,7 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { ...@@ -2620,7 +2620,7 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
FixedArray::kHeaderSize + node->literal_index() * kPointerSize; FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
__ ldr(r2, FieldMemOperand(r1, literal_offset)); __ ldr(r2, FieldMemOperand(r1, literal_offset));
JumpTarget done(this); JumpTarget done;
__ cmp(r2, Operand(Factory::undefined_value())); __ cmp(r2, Operand(Factory::undefined_value()));
done.Branch(ne); done.Branch(ne);
...@@ -3266,7 +3266,7 @@ void CodeGenerator::VisitCallNew(CallNew* node) { ...@@ -3266,7 +3266,7 @@ void CodeGenerator::VisitCallNew(CallNew* node) {
void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope(this); VirtualFrame::SpilledScope spilled_scope(this);
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
JumpTarget leave(this); JumpTarget leave;
LoadAndSpill(args->at(0)); LoadAndSpill(args->at(0));
frame_->EmitPop(r0); // r0 contains object. frame_->EmitPop(r0); // r0 contains object.
// if (object->IsSmi()) return the object. // if (object->IsSmi()) return the object.
...@@ -3288,7 +3288,7 @@ void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { ...@@ -3288,7 +3288,7 @@ void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope(this); VirtualFrame::SpilledScope spilled_scope(this);
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
JumpTarget leave(this); JumpTarget leave;
LoadAndSpill(args->at(0)); // Load the object. LoadAndSpill(args->at(0)); // Load the object.
LoadAndSpill(args->at(1)); // Load the value. LoadAndSpill(args->at(1)); // Load the value.
frame_->EmitPop(r0); // r0 contains value frame_->EmitPop(r0); // r0 contains value
...@@ -3364,7 +3364,7 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { ...@@ -3364,7 +3364,7 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope(this); VirtualFrame::SpilledScope spilled_scope(this);
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
LoadAndSpill(args->at(0)); LoadAndSpill(args->at(0));
JumpTarget answer(this); JumpTarget answer;
// We need the CC bits to come out as not_equal in the case where the // We need the CC bits to come out as not_equal in the case where the
// object is a smi. This can't be done with the usual test opcode so // object is a smi. This can't be done with the usual test opcode so
// we use XOR to get the right CC bits. // we use XOR to get the right CC bits.
...@@ -3568,8 +3568,8 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { ...@@ -3568,8 +3568,8 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
case Token::BIT_NOT: { case Token::BIT_NOT: {
// smi check // smi check
JumpTarget smi_label(this); JumpTarget smi_label;
JumpTarget continue_label(this); JumpTarget continue_label;
__ tst(r0, Operand(kSmiTagMask)); __ tst(r0, Operand(kSmiTagMask));
smi_label.Branch(eq); smi_label.Branch(eq);
...@@ -3595,7 +3595,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { ...@@ -3595,7 +3595,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
case Token::ADD: { case Token::ADD: {
// Smi check. // Smi check.
JumpTarget continue_label(this); JumpTarget continue_label;
__ tst(r0, Operand(kSmiTagMask)); __ tst(r0, Operand(kSmiTagMask));
continue_label.Branch(eq); continue_label.Branch(eq);
frame_->EmitPush(r0); frame_->EmitPush(r0);
...@@ -3649,8 +3649,8 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) { ...@@ -3649,8 +3649,8 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
target.GetValueAndSpill(NOT_INSIDE_TYPEOF); target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
frame_->EmitPop(r0); frame_->EmitPop(r0);
JumpTarget slow(this); JumpTarget slow;
JumpTarget exit(this); JumpTarget exit;
// Load the value (1) into register r1. // Load the value (1) into register r1.
__ mov(r1, Operand(Smi::FromInt(1))); __ mov(r1, Operand(Smi::FromInt(1)));
...@@ -3739,7 +3739,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -3739,7 +3739,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// of compiling the binary operation is materialized or not. // of compiling the binary operation is materialized or not.
if (op == Token::AND) { if (op == Token::AND) {
JumpTarget is_true(this); JumpTarget is_true;
LoadConditionAndSpill(node->left(), LoadConditionAndSpill(node->left(),
NOT_INSIDE_TYPEOF, NOT_INSIDE_TYPEOF,
&is_true, &is_true,
...@@ -3757,8 +3757,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -3757,8 +3757,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
false); false);
} else { } else {
JumpTarget pop_and_continue(this); JumpTarget pop_and_continue;
JumpTarget exit(this); JumpTarget exit;
__ ldr(r0, frame_->Top()); // dup the stack top __ ldr(r0, frame_->Top()); // dup the stack top
frame_->EmitPush(r0); frame_->EmitPush(r0);
...@@ -3781,7 +3781,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -3781,7 +3781,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
} }
} else if (op == Token::OR) { } else if (op == Token::OR) {
JumpTarget is_false(this); JumpTarget is_false;
LoadConditionAndSpill(node->left(), LoadConditionAndSpill(node->left(),
NOT_INSIDE_TYPEOF, NOT_INSIDE_TYPEOF,
true_target(), true_target(),
...@@ -3799,8 +3799,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -3799,8 +3799,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
false); false);
} else { } else {
JumpTarget pop_and_continue(this); JumpTarget pop_and_continue;
JumpTarget exit(this); JumpTarget exit;
__ ldr(r0, frame_->Top()); __ ldr(r0, frame_->Top());
frame_->EmitPush(r0); frame_->EmitPush(r0);
...@@ -4241,7 +4241,7 @@ void Reference::SetValue(InitState init_state) { ...@@ -4241,7 +4241,7 @@ void Reference::SetValue(InitState init_state) {
} else { } else {
ASSERT(!slot->var()->is_dynamic()); ASSERT(!slot->var()->is_dynamic());
JumpTarget exit(cgen_); JumpTarget exit;
if (init_state == CONST_INIT) { if (init_state == CONST_INIT) {
ASSERT(slot->var()->mode() == Variable::CONST); ASSERT(slot->var()->mode() == Variable::CONST);
// Only the first const initialization must be executed (the slot // Only the first const initialization must be executed (the slot
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "v8.h" #include "v8.h"
#include "codegen-inl.h" #include "codegen-inl.h"
#include "jump-target-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
namespace v8 { namespace internal { namespace v8 { namespace internal {
...@@ -35,21 +36,20 @@ namespace v8 { namespace internal { ...@@ -35,21 +36,20 @@ namespace v8 { namespace internal {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// JumpTarget implementation. // JumpTarget implementation.
#define __ ACCESS_MASM(masm_) #define __ ACCESS_MASM(cgen()->masm())
void JumpTarget::DoJump() { void JumpTarget::DoJump() {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
// Live non-frame registers are not allowed at unconditional jumps // Live non-frame registers are not allowed at unconditional jumps
// because we have no way of invalidating the corresponding results // because we have no way of invalidating the corresponding results
// which are still live in the C++ code. // which are still live in the C++ code.
ASSERT(cgen_->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
if (is_bound()) { if (is_bound()) {
// Backward jump. There is an expected frame to merge to. // Backward jump. There is an expected frame to merge to.
ASSERT(direction_ == BIDIRECTIONAL); ASSERT(direction_ == BIDIRECTIONAL);
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ jmp(&entry_label_); __ jmp(&entry_label_);
} else { } else {
// Preconfigured entry frame is not used on ARM. // Preconfigured entry frame is not used on ARM.
...@@ -57,17 +57,16 @@ void JumpTarget::DoJump() { ...@@ -57,17 +57,16 @@ void JumpTarget::DoJump() {
// Forward jump. The current frame is added to the end of the list // Forward jump. The current frame is added to the end of the list
// of frames reaching the target block and a jump to the merge code // of frames reaching the target block and a jump to the merge code
// is emitted. // is emitted.
AddReachingFrame(cgen_->frame()); AddReachingFrame(cgen()->frame());
RegisterFile empty; RegisterFile empty;
cgen_->SetFrame(NULL, &empty); cgen()->SetFrame(NULL, &empty);
__ jmp(&merge_labels_.last()); __ jmp(&merge_labels_.last());
} }
} }
void JumpTarget::DoBranch(Condition cc, Hint ignored) { void JumpTarget::DoBranch(Condition cc, Hint ignored) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
if (is_bound()) { if (is_bound()) {
ASSERT(direction_ == BIDIRECTIONAL); ASSERT(direction_ == BIDIRECTIONAL);
...@@ -77,29 +76,29 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) { ...@@ -77,29 +76,29 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) {
// Swap the current frame for a copy (we do the swapping to get // Swap the current frame for a copy (we do the swapping to get
// the off-frame registers off the fall through) to use for the // the off-frame registers off the fall through) to use for the
// branch. // branch.
VirtualFrame* fall_through_frame = cgen_->frame(); VirtualFrame* fall_through_frame = cgen()->frame();
VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame); VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame);
RegisterFile non_frame_registers = RegisterAllocator::Reserved(); RegisterFile non_frame_registers = RegisterAllocator::Reserved();
cgen_->SetFrame(branch_frame, &non_frame_registers); cgen()->SetFrame(branch_frame, &non_frame_registers);
// Check if we can avoid merge code. // Check if we can avoid merge code.
cgen_->frame()->PrepareMergeTo(entry_frame_); cgen()->frame()->PrepareMergeTo(entry_frame_);
if (cgen_->frame()->Equals(entry_frame_)) { if (cgen()->frame()->Equals(entry_frame_)) {
// Branch right in to the block. // Branch right in to the block.
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ b(cc, &entry_label_); __ b(cc, &entry_label_);
cgen_->SetFrame(fall_through_frame, &non_frame_registers); cgen()->SetFrame(fall_through_frame, &non_frame_registers);
return; return;
} }
// Check if we can reuse existing merge code. // Check if we can reuse existing merge code.
for (int i = 0; i < reaching_frames_.length(); i++) { for (int i = 0; i < reaching_frames_.length(); i++) {
if (reaching_frames_[i] != NULL && if (reaching_frames_[i] != NULL &&
cgen_->frame()->Equals(reaching_frames_[i])) { cgen()->frame()->Equals(reaching_frames_[i])) {
// Branch to the merge code. // Branch to the merge code.
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ b(cc, &merge_labels_[i]); __ b(cc, &merge_labels_[i]);
cgen_->SetFrame(fall_through_frame, &non_frame_registers); cgen()->SetFrame(fall_through_frame, &non_frame_registers);
return; return;
} }
} }
...@@ -108,10 +107,10 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) { ...@@ -108,10 +107,10 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) {
// around the merge code on the fall through path. // around the merge code on the fall through path.
Label original_fall_through; Label original_fall_through;
__ b(NegateCondition(cc), &original_fall_through); __ b(NegateCondition(cc), &original_fall_through);
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ b(&entry_label_); __ b(&entry_label_);
cgen_->SetFrame(fall_through_frame, &non_frame_registers); cgen()->SetFrame(fall_through_frame, &non_frame_registers);
__ bind(&original_fall_through); __ bind(&original_fall_through);
} else { } else {
...@@ -120,7 +119,7 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) { ...@@ -120,7 +119,7 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) {
// Forward branch. A copy of the current frame is added to the end // Forward branch. A copy of the current frame is added to the end
// of the list of frames reaching the target block and a branch to // of the list of frames reaching the target block and a branch to
// the merge code is emitted. // the merge code is emitted.
AddReachingFrame(new VirtualFrame(cgen_->frame())); AddReachingFrame(new VirtualFrame(cgen()->frame()));
__ b(cc, &merge_labels_.last()); __ b(cc, &merge_labels_.last());
} }
} }
...@@ -133,14 +132,13 @@ void JumpTarget::Call() { ...@@ -133,14 +132,13 @@ void JumpTarget::Call() {
// at the label (which should be the only one) is the spilled current // at the label (which should be the only one) is the spilled current
// frame plus an in-memory return address. The "fall-through" frame // frame plus an in-memory return address. The "fall-through" frame
// at the return site is the spilled current frame. // at the return site is the spilled current frame.
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
// There are no non-frame references across the call. // There are no non-frame references across the call.
ASSERT(cgen_->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
ASSERT(!is_linked()); ASSERT(!is_linked());
cgen_->frame()->SpillAll(); cgen()->frame()->SpillAll();
VirtualFrame* target_frame = new VirtualFrame(cgen_->frame()); VirtualFrame* target_frame = new VirtualFrame(cgen()->frame());
target_frame->Adjust(1); target_frame->Adjust(1);
// We do not expect a call with a preconfigured entry frame. // We do not expect a call with a preconfigured entry frame.
ASSERT(entry_frame_ == NULL); ASSERT(entry_frame_ == NULL);
...@@ -150,20 +148,19 @@ void JumpTarget::Call() { ...@@ -150,20 +148,19 @@ void JumpTarget::Call() {
void JumpTarget::DoBind(int mergable_elements) { void JumpTarget::DoBind(int mergable_elements) {
ASSERT(cgen_ != NULL);
ASSERT(!is_bound()); ASSERT(!is_bound());
// Live non-frame registers are not allowed at the start of a basic // Live non-frame registers are not allowed at the start of a basic
// block. // block.
ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters()); ASSERT(!cgen()->has_valid_frame() || cgen()->HasValidEntryRegisters());
if (direction_ == FORWARD_ONLY) { if (direction_ == FORWARD_ONLY) {
// A simple case: no forward jumps and no possible backward jumps. // A simple case: no forward jumps and no possible backward jumps.
if (!is_linked()) { if (!is_linked()) {
// The stack pointer can be floating above the top of the // The stack pointer can be floating above the top of the
// virtual frame before the bind. Afterward, it should not. // virtual frame before the bind. Afterward, it should not.
ASSERT(cgen_->has_valid_frame()); ASSERT(cgen()->has_valid_frame());
VirtualFrame* frame = cgen_->frame(); VirtualFrame* frame = cgen()->frame();
int difference = int difference =
frame->stack_pointer_ - (frame->elements_.length() - 1); frame->stack_pointer_ - (frame->elements_.length() - 1);
if (difference > 0) { if (difference > 0) {
...@@ -176,12 +173,12 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -176,12 +173,12 @@ void JumpTarget::DoBind(int mergable_elements) {
// Another simple case: no fall through, a single forward jump, // Another simple case: no fall through, a single forward jump,
// and no possible backward jumps. // and no possible backward jumps.
if (!cgen_->has_valid_frame() && reaching_frames_.length() == 1) { if (!cgen()->has_valid_frame() && reaching_frames_.length() == 1) {
// Pick up the only reaching frame, take ownership of it, and // Pick up the only reaching frame, take ownership of it, and
// use it for the block about to be emitted. // use it for the block about to be emitted.
VirtualFrame* frame = reaching_frames_[0]; VirtualFrame* frame = reaching_frames_[0];
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &reserved);
reaching_frames_[0] = NULL; reaching_frames_[0] = NULL;
__ bind(&merge_labels_[0]); __ bind(&merge_labels_[0]);
...@@ -201,11 +198,11 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -201,11 +198,11 @@ void JumpTarget::DoBind(int mergable_elements) {
// If there is a current frame, record it as the fall-through. It // If there is a current frame, record it as the fall-through. It
// is owned by the reaching frames for now. // is owned by the reaching frames for now.
bool had_fall_through = false; bool had_fall_through = false;
if (cgen_->has_valid_frame()) { if (cgen()->has_valid_frame()) {
had_fall_through = true; had_fall_through = true;
AddReachingFrame(cgen_->frame()); // Return value ignored. AddReachingFrame(cgen()->frame()); // Return value ignored.
RegisterFile empty; RegisterFile empty;
cgen_->SetFrame(NULL, &empty); cgen()->SetFrame(NULL, &empty);
} }
// Compute the frame to use for entry to the block. // Compute the frame to use for entry to the block.
...@@ -242,17 +239,17 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -242,17 +239,17 @@ void JumpTarget::DoBind(int mergable_elements) {
// binding site or as the fall through from a previous merge // binding site or as the fall through from a previous merge
// code block. Jump around the code we are about to // code block. Jump around the code we are about to
// generate. // generate.
if (cgen_->has_valid_frame()) { if (cgen()->has_valid_frame()) {
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ b(&entry_label_); __ b(&entry_label_);
} }
// Pick up the frame for this block. Assume ownership if // Pick up the frame for this block. Assume ownership if
// there cannot be backward jumps. // there cannot be backward jumps.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile reserved = RegisterAllocator::Reserved();
if (direction_ == BIDIRECTIONAL) { if (direction_ == BIDIRECTIONAL) {
cgen_->SetFrame(new VirtualFrame(frame), &reserved); cgen()->SetFrame(new VirtualFrame(frame), &reserved);
} else { } else {
cgen_->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &reserved);
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
} }
__ bind(&merge_labels_[i]); __ bind(&merge_labels_[i]);
...@@ -261,7 +258,7 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -261,7 +258,7 @@ void JumpTarget::DoBind(int mergable_elements) {
// looking for any that can share merge code with this one. // looking for any that can share merge code with this one.
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
VirtualFrame* other = reaching_frames_[j]; VirtualFrame* other = reaching_frames_[j];
if (other != NULL && other->Equals(cgen_->frame())) { if (other != NULL && other->Equals(cgen()->frame())) {
// Set the reaching frame element to null to avoid // Set the reaching frame element to null to avoid
// processing it later, and then bind its entry label. // processing it later, and then bind its entry label.
reaching_frames_[j] = NULL; reaching_frames_[j] = NULL;
...@@ -270,13 +267,13 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -270,13 +267,13 @@ void JumpTarget::DoBind(int mergable_elements) {
} }
// Emit the merge code. // Emit the merge code.
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
} else if (i == reaching_frames_.length() - 1 && had_fall_through) { } else if (i == reaching_frames_.length() - 1 && had_fall_through) {
// If this is the fall through, and it didn't need merge // If this is the fall through, and it didn't need merge
// code, we need to pick up the frame so we can jump around // code, we need to pick up the frame so we can jump around
// subsequent merge blocks if necessary. // subsequent merge blocks if necessary.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &reserved);
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
} }
} }
...@@ -285,9 +282,9 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -285,9 +282,9 @@ void JumpTarget::DoBind(int mergable_elements) {
// The code generator may not have a current frame if there was no // The code generator may not have a current frame if there was no
// fall through and none of the reaching frames needed merging. // fall through and none of the reaching frames needed merging.
// In that case, clone the entry frame as the current frame. // In that case, clone the entry frame as the current frame.
if (!cgen_->has_valid_frame()) { if (!cgen()->has_valid_frame()) {
RegisterFile reserved_registers = RegisterAllocator::Reserved(); RegisterFile reserved_registers = RegisterAllocator::Reserved();
cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers); cgen()->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers);
} }
// There may be unprocessed reaching frames that did not need // There may be unprocessed reaching frames that did not need
...@@ -313,9 +310,9 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -313,9 +310,9 @@ void JumpTarget::DoBind(int mergable_elements) {
// Use a copy of the reaching frame so the original can be saved // Use a copy of the reaching frame so the original can be saved
// for possible reuse as a backward merge block. // for possible reuse as a backward merge block.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved); cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved);
__ bind(&merge_labels_[0]); __ bind(&merge_labels_[0]);
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
} }
__ bind(&entry_label_); __ bind(&entry_label_);
......
...@@ -47,8 +47,7 @@ CodeGenerator* CodeGeneratorScope::top_ = NULL; ...@@ -47,8 +47,7 @@ CodeGenerator* CodeGeneratorScope::top_ = NULL;
DeferredCode::DeferredCode(CodeGenerator* generator) DeferredCode::DeferredCode(CodeGenerator* generator)
: generator_(generator), : generator_(generator),
masm_(generator->masm()), masm_(generator->masm()),
enter_(generator), exit_(JumpTarget::BIDIRECTIONAL),
exit_(generator, JumpTarget::BIDIRECTIONAL),
statement_position_(masm_->current_statement_position()), statement_position_(masm_->current_statement_position()),
position_(masm_->current_position()) { position_(masm_->current_position()) {
generator->AddDeferred(this); generator->AddDeferred(this);
......
...@@ -141,7 +141,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { ...@@ -141,7 +141,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
frame_->AllocateStackSlots(scope_->num_stack_slots()); frame_->AllocateStackSlots(scope_->num_stack_slots());
// Initialize the function return target after the locals are set // Initialize the function return target after the locals are set
// up, because it needs the expected frame height from the frame. // up, because it needs the expected frame height from the frame.
function_return_.Initialize(this, JumpTarget::BIDIRECTIONAL); function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
function_return_is_shadowed_ = false; function_return_is_shadowed_ = false;
// Allocate the arguments object and copy the parameters into it. // Allocate the arguments object and copy the parameters into it.
...@@ -468,14 +468,14 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { ...@@ -468,14 +468,14 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
int original_height = frame_->height(); int original_height = frame_->height();
#endif #endif
ASSERT(!in_spilled_code()); ASSERT(!in_spilled_code());
JumpTarget true_target(this); JumpTarget true_target;
JumpTarget false_target(this); JumpTarget false_target;
ControlDestination dest(&true_target, &false_target, true); ControlDestination dest(&true_target, &false_target, true);
LoadCondition(x, typeof_state, &dest, false); LoadCondition(x, typeof_state, &dest, false);
if (dest.false_was_fall_through()) { if (dest.false_was_fall_through()) {
// The false target was just bound. // The false target was just bound.
JumpTarget loaded(this); JumpTarget loaded;
frame_->Push(Factory::false_value()); frame_->Push(Factory::false_value());
// There may be dangling jumps to the true target. // There may be dangling jumps to the true target.
if (true_target.is_linked()) { if (true_target.is_linked()) {
...@@ -488,7 +488,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { ...@@ -488,7 +488,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
} else if (dest.is_used()) { } else if (dest.is_used()) {
// There is true, and possibly false, control flow (with true as // There is true, and possibly false, control flow (with true as
// the fall through). // the fall through).
JumpTarget loaded(this); JumpTarget loaded;
frame_->Push(Factory::true_value()); frame_->Push(Factory::true_value());
if (false_target.is_linked()) { if (false_target.is_linked()) {
loaded.Jump(); loaded.Jump();
...@@ -504,7 +504,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { ...@@ -504,7 +504,7 @@ void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
// short-circuited boolean operators). // short-circuited boolean operators).
ASSERT(has_valid_frame()); ASSERT(has_valid_frame());
if (true_target.is_linked() || false_target.is_linked()) { if (true_target.is_linked() || false_target.is_linked()) {
JumpTarget loaded(this); JumpTarget loaded;
loaded.Jump(); // Don't lose the current TOS. loaded.Jump(); // Don't lose the current TOS.
if (true_target.is_linked()) { if (true_target.is_linked()) {
true_target.Bind(); true_target.Bind();
...@@ -1541,7 +1541,7 @@ void CodeGenerator::Comparison(Condition cc, ...@@ -1541,7 +1541,7 @@ void CodeGenerator::Comparison(Condition cc,
// where both sides are Smis. // where both sides are Smis.
left_side.ToRegister(); left_side.ToRegister();
ASSERT(left_side.is_valid()); ASSERT(left_side.is_valid());
JumpTarget is_smi(this); JumpTarget is_smi;
__ test(left_side.reg(), Immediate(kSmiTagMask)); __ test(left_side.reg(), Immediate(kSmiTagMask));
is_smi.Branch(zero, &left_side, &right_side, taken); is_smi.Branch(zero, &left_side, &right_side, taken);
...@@ -1612,7 +1612,7 @@ void CodeGenerator::Comparison(Condition cc, ...@@ -1612,7 +1612,7 @@ void CodeGenerator::Comparison(Condition cc,
(right_side.is_constant() && !right_side.handle()->IsSmi()); (right_side.is_constant() && !right_side.handle()->IsSmi());
left_side.ToRegister(); left_side.ToRegister();
right_side.ToRegister(); right_side.ToRegister();
JumpTarget is_smi(this); JumpTarget is_smi;
if (!known_non_smi) { if (!known_non_smi) {
// Check for the smi case. // Check for the smi case.
Result temp = allocator_->Allocate(); Result temp = allocator_->Allocate();
...@@ -1757,7 +1757,7 @@ void CodeGenerator::VisitBlock(Block* node) { ...@@ -1757,7 +1757,7 @@ void CodeGenerator::VisitBlock(Block* node) {
ASSERT(!in_spilled_code()); ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ Block"); Comment cmnt(masm_, "[ Block");
CodeForStatementPosition(node); CodeForStatementPosition(node);
node->break_target()->Initialize(this); node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
VisitStatements(node->statements()); VisitStatements(node->statements());
if (node->break_target()->is_linked()) { if (node->break_target()->is_linked()) {
node->break_target()->Bind(); node->break_target()->Bind();
...@@ -1871,10 +1871,10 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) { ...@@ -1871,10 +1871,10 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
bool has_else_stm = node->HasElseStatement(); bool has_else_stm = node->HasElseStatement();
CodeForStatementPosition(node); CodeForStatementPosition(node);
JumpTarget exit(this); JumpTarget exit;
if (has_then_stm && has_else_stm) { if (has_then_stm && has_else_stm) {
JumpTarget then(this); JumpTarget then;
JumpTarget else_(this); JumpTarget else_;
ControlDestination dest(&then, &else_, true); ControlDestination dest(&then, &else_, true);
LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
...@@ -1901,7 +1901,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) { ...@@ -1901,7 +1901,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
} else if (has_then_stm) { } else if (has_then_stm) {
ASSERT(!has_else_stm); ASSERT(!has_else_stm);
JumpTarget then(this); JumpTarget then;
ControlDestination dest(&then, &exit, true); ControlDestination dest(&then, &exit, true);
LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
...@@ -1921,7 +1921,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) { ...@@ -1921,7 +1921,7 @@ void CodeGenerator::VisitIfStatement(IfStatement* node) {
} else if (has_else_stm) { } else if (has_else_stm) {
ASSERT(!has_then_stm); ASSERT(!has_then_stm);
JumpTarget else_(this); JumpTarget else_;
ControlDestination dest(&exit, &else_, false); ControlDestination dest(&exit, &else_, false);
LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
...@@ -2088,8 +2088,8 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable( ...@@ -2088,8 +2088,8 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
// placeholders, and fill in the addresses after the labels have been // placeholders, and fill in the addresses after the labels have been
// bound. // bound.
JumpTarget setup_default(this); JumpTarget setup_default;
JumpTarget is_smi(this); JumpTarget is_smi;
// A non-null default label pointer indicates a default case among // A non-null default label pointer indicates a default case among
// the case labels. Otherwise we use the break target as a // the case labels. Otherwise we use the break target as a
...@@ -2134,7 +2134,7 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable( ...@@ -2134,7 +2134,7 @@ void CodeGenerator::GenerateFastCaseSwitchJumpTable(
// frame of the correct height can be merged to). Keep a copy to // frame of the correct height can be merged to). Keep a copy to
// restore at the start of every label. Create a jump target and // restore at the start of every label. Create a jump target and
// bind it to set its entry frame properly. // bind it to set its entry frame properly.
JumpTarget entry_target(this, JumpTarget::BIDIRECTIONAL); JumpTarget entry_target(JumpTarget::BIDIRECTIONAL);
entry_target.Bind(&smi_value); entry_target.Bind(&smi_value);
VirtualFrame* start_frame = new VirtualFrame(frame_); VirtualFrame* start_frame = new VirtualFrame(frame_);
...@@ -2191,7 +2191,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { ...@@ -2191,7 +2191,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
ASSERT(!in_spilled_code()); ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ SwitchStatement"); Comment cmnt(masm_, "[ SwitchStatement");
CodeForStatementPosition(node); CodeForStatementPosition(node);
node->break_target()->Initialize(this); node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
// Compile the switch value. // Compile the switch value.
Load(node->tag()); Load(node->tag());
...@@ -2204,7 +2204,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { ...@@ -2204,7 +2204,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
int length = cases->length(); int length = cases->length();
CaseClause* default_clause = NULL; CaseClause* default_clause = NULL;
JumpTarget next_test(this); JumpTarget next_test;
// Compile the case label expressions and comparisons. Exit early // Compile the case label expressions and comparisons. Exit early
// if a comparison is unconditionally true. The target next_test is // if a comparison is unconditionally true. The target next_test is
// bound before the loop in order to indicate control flow to the // bound before the loop in order to indicate control flow to the
...@@ -2212,7 +2212,6 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { ...@@ -2212,7 +2212,6 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
next_test.Bind(); next_test.Bind();
for (int i = 0; i < length && !next_test.is_unused(); i++) { for (int i = 0; i < length && !next_test.is_unused(); i++) {
CaseClause* clause = cases->at(i); CaseClause* clause = cases->at(i);
clause->body_target()->Initialize(this);
// The default is not a test, but remember it for later. // The default is not a test, but remember it for later.
if (clause->is_default()) { if (clause->is_default()) {
default_clause = clause; default_clause = clause;
...@@ -2283,7 +2282,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { ...@@ -2283,7 +2282,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
if (clause->is_default()) { if (clause->is_default()) {
clause->body_target()->Bind(); clause->body_target()->Bind();
} else { } else {
JumpTarget body(this); JumpTarget body;
body.Jump(); body.Jump();
clause->body_target()->Bind(); clause->body_target()->Bind();
frame_->Drop(); frame_->Drop();
...@@ -2321,7 +2320,7 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -2321,7 +2320,7 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
ASSERT(!in_spilled_code()); ASSERT(!in_spilled_code());
Comment cmnt(masm_, "[ LoopStatement"); Comment cmnt(masm_, "[ LoopStatement");
CodeForStatementPosition(node); CodeForStatementPosition(node);
node->break_target()->Initialize(this); node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
// Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a // Simple condition analysis. ALWAYS_TRUE and ALWAYS_FALSE represent a
// known result for the test expression, with no side effects. // known result for the test expression, with no side effects.
...@@ -2342,21 +2341,21 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -2342,21 +2341,21 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
switch (node->type()) { switch (node->type()) {
case LoopStatement::DO_LOOP: { case LoopStatement::DO_LOOP: {
JumpTarget body(this, JumpTarget::BIDIRECTIONAL); JumpTarget body(JumpTarget::BIDIRECTIONAL);
IncrementLoopNesting(); IncrementLoopNesting();
// Label the top of the loop for the backward jump if necessary. // Label the top of the loop for the backward jump if necessary.
if (info == ALWAYS_TRUE) { if (info == ALWAYS_TRUE) {
// Use the continue target. // Use the continue target.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind(); node->continue_target()->Bind();
} else if (info == ALWAYS_FALSE) { } else if (info == ALWAYS_FALSE) {
// No need to label it. // No need to label it.
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
} else { } else {
// Continue is the test, so use the backward body target. // Continue is the test, so use the backward body target.
ASSERT(info == DONT_KNOW); ASSERT(info == DONT_KNOW);
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
body.Bind(); body.Bind();
} }
...@@ -2415,27 +2414,25 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -2415,27 +2414,25 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
JumpTarget body; JumpTarget body;
if (test_at_bottom) { if (test_at_bottom) {
body.Initialize(this, JumpTarget::BIDIRECTIONAL); body.set_direction(JumpTarget::BIDIRECTIONAL);
} else {
body.Initialize(this);
} }
// Based on the condition analysis, compile the test as necessary. // Based on the condition analysis, compile the test as necessary.
if (info == ALWAYS_TRUE) { if (info == ALWAYS_TRUE) {
// We will not compile the test expression. Label the top of // We will not compile the test expression. Label the top of
// the loop with the continue target. // the loop with the continue target.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind(); node->continue_target()->Bind();
} else { } else {
ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here. ASSERT(info == DONT_KNOW); // ALWAYS_FALSE cannot reach here.
if (test_at_bottom) { if (test_at_bottom) {
// Continue is the test at the bottom, no need to label the // Continue is the test at the bottom, no need to label the
// test at the top. The body is a backward target. // test at the top. The body is a backward target.
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
} else { } else {
// Label the test at the top as the continue target. The // Label the test at the top as the continue target. The
// body is a forward-only target. // body is a forward-only target.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind(); node->continue_target()->Bind();
} }
// Compile the test with the body as the true target and // Compile the test with the body as the true target and
...@@ -2518,15 +2515,13 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -2518,15 +2515,13 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
// Target for backward edge if no test at the bottom, otherwise // Target for backward edge if no test at the bottom, otherwise
// unused. // unused.
JumpTarget loop(this, JumpTarget::BIDIRECTIONAL); JumpTarget loop(JumpTarget::BIDIRECTIONAL);
// Target for backward edge if there is a test at the bottom, // Target for backward edge if there is a test at the bottom,
// otherwise used as target for test at the top. // otherwise used as target for test at the top.
JumpTarget body; JumpTarget body;
if (test_at_bottom) { if (test_at_bottom) {
body.Initialize(this, JumpTarget::BIDIRECTIONAL); body.set_direction(JumpTarget::BIDIRECTIONAL);
} else {
body.Initialize(this);
} }
// Based on the condition analysis, compile the test as necessary. // Based on the condition analysis, compile the test as necessary.
...@@ -2535,11 +2530,11 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -2535,11 +2530,11 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
// the loop. // the loop.
if (node->next() == NULL) { if (node->next() == NULL) {
// Use the continue target if there is no update expression. // Use the continue target if there is no update expression.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind(); node->continue_target()->Bind();
} else { } else {
// Otherwise use the backward loop target. // Otherwise use the backward loop target.
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
loop.Bind(); loop.Bind();
} }
} else { } else {
...@@ -2547,16 +2542,16 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) { ...@@ -2547,16 +2542,16 @@ void CodeGenerator::VisitLoopStatement(LoopStatement* node) {
if (test_at_bottom) { if (test_at_bottom) {
// Continue is either the update expression or the test at // Continue is either the update expression or the test at
// the bottom, no need to label the test at the top. // the bottom, no need to label the test at the top.
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
} else if (node->next() == NULL) { } else if (node->next() == NULL) {
// We are not recompiling the test at the bottom and there // We are not recompiling the test at the bottom and there
// is no update expression. // is no update expression.
node->continue_target()->Initialize(this, JumpTarget::BIDIRECTIONAL); node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
node->continue_target()->Bind(); node->continue_target()->Bind();
} else { } else {
// We are not recompiling the test at the bottom and there // We are not recompiling the test at the bottom and there
// is an update expression. // is an update expression.
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
loop.Bind(); loop.Bind();
} }
...@@ -2660,12 +2655,12 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -2660,12 +2655,12 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
Comment cmnt(masm_, "[ ForInStatement"); Comment cmnt(masm_, "[ ForInStatement");
CodeForStatementPosition(node); CodeForStatementPosition(node);
JumpTarget primitive(this); JumpTarget primitive;
JumpTarget jsobject(this); JumpTarget jsobject;
JumpTarget fixed_array(this); JumpTarget fixed_array;
JumpTarget entry(this, JumpTarget::BIDIRECTIONAL); JumpTarget entry(JumpTarget::BIDIRECTIONAL);
JumpTarget end_del_check(this); JumpTarget end_del_check;
JumpTarget exit(this); JumpTarget exit;
// Get the object to enumerate over (converted to JSObject). // Get the object to enumerate over (converted to JSObject).
LoadAndSpill(node->enumerable()); LoadAndSpill(node->enumerable());
...@@ -2750,8 +2745,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) { ...@@ -2750,8 +2745,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
entry.Bind(); entry.Bind();
// Grab the current frame's height for the break and continue // Grab the current frame's height for the break and continue
// targets only after all the state is pushed on the frame. // targets only after all the state is pushed on the frame.
node->break_target()->Initialize(this); node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
node->continue_target()->Initialize(this); node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
__ mov(eax, frame_->ElementAt(0)); // load the current count __ mov(eax, frame_->ElementAt(0)); // load the current count
__ cmp(eax, frame_->ElementAt(1)); // compare to the array length __ cmp(eax, frame_->ElementAt(1)); // compare to the array length
...@@ -2850,8 +2845,8 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) { ...@@ -2850,8 +2845,8 @@ void CodeGenerator::VisitTryCatch(TryCatch* node) {
Comment cmnt(masm_, "[ TryCatch"); Comment cmnt(masm_, "[ TryCatch");
CodeForStatementPosition(node); CodeForStatementPosition(node);
JumpTarget try_block(this); JumpTarget try_block;
JumpTarget exit(this); JumpTarget exit;
try_block.Call(); try_block.Call();
// --- Catch block --- // --- Catch block ---
...@@ -2994,8 +2989,8 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -2994,8 +2989,8 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
// break/continue from within the try block. // break/continue from within the try block.
enum { FALLING, THROWING, JUMPING }; enum { FALLING, THROWING, JUMPING };
JumpTarget try_block(this); JumpTarget try_block;
JumpTarget finally_block(this); JumpTarget finally_block;
try_block.Call(); try_block.Call();
...@@ -3147,7 +3142,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -3147,7 +3142,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
} else { } else {
// Branch around the preparation for return which may emit // Branch around the preparation for return which may emit
// code. // code.
JumpTarget skip(this); JumpTarget skip;
skip.Branch(not_equal); skip.Branch(not_equal);
frame_->PrepareForReturn(); frame_->PrepareForReturn();
original->Jump(&return_value); original->Jump(&return_value);
...@@ -3161,7 +3156,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) { ...@@ -3161,7 +3156,7 @@ void CodeGenerator::VisitTryFinally(TryFinally* node) {
if (has_valid_frame()) { if (has_valid_frame()) {
// Check if we need to rethrow the exception. // Check if we need to rethrow the exception.
JumpTarget exit(this); JumpTarget exit;
__ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING))); __ cmp(Operand(ecx), Immediate(Smi::FromInt(THROWING)));
exit.Branch(not_equal); exit.Branch(not_equal);
...@@ -3221,9 +3216,9 @@ void CodeGenerator::VisitFunctionBoilerplateLiteral( ...@@ -3221,9 +3216,9 @@ void CodeGenerator::VisitFunctionBoilerplateLiteral(
void CodeGenerator::VisitConditional(Conditional* node) { void CodeGenerator::VisitConditional(Conditional* node) {
Comment cmnt(masm_, "[ Conditional"); Comment cmnt(masm_, "[ Conditional");
JumpTarget then(this); JumpTarget then;
JumpTarget else_(this); JumpTarget else_;
JumpTarget exit(this); JumpTarget exit;
ControlDestination dest(&then, &else_, true); ControlDestination dest(&then, &else_, true);
LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true); LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &dest, true);
...@@ -3255,8 +3250,8 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -3255,8 +3250,8 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
if (slot->type() == Slot::LOOKUP) { if (slot->type() == Slot::LOOKUP) {
ASSERT(slot->var()->is_dynamic()); ASSERT(slot->var()->is_dynamic());
JumpTarget slow(this); JumpTarget slow;
JumpTarget done(this); JumpTarget done;
Result value; Result value;
// Generate fast-case code for variables that might be shadowed by // Generate fast-case code for variables that might be shadowed by
...@@ -3322,7 +3317,7 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { ...@@ -3322,7 +3317,7 @@ void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
// potentially unsafe direct-frame access of SlotOperand. // potentially unsafe direct-frame access of SlotOperand.
VirtualFrame::SpilledScope spilled_scope(this); VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ Load const"); Comment cmnt(masm_, "[ Load const");
JumpTarget exit(this); JumpTarget exit;
__ mov(ecx, SlotOperand(slot, ecx)); __ mov(ecx, SlotOperand(slot, ecx));
__ cmp(ecx, Factory::the_hole_value()); __ cmp(ecx, Factory::the_hole_value());
exit.Branch(not_equal); exit.Branch(not_equal);
...@@ -3460,7 +3455,7 @@ void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { ...@@ -3460,7 +3455,7 @@ void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
} else { } else {
ASSERT(!slot->var()->is_dynamic()); ASSERT(!slot->var()->is_dynamic());
JumpTarget exit(this); JumpTarget exit;
if (init_state == CONST_INIT) { if (init_state == CONST_INIT) {
ASSERT(slot->var()->mode() == Variable::CONST); ASSERT(slot->var()->mode() == Variable::CONST);
// Only the first const initialization must be executed (the slot // Only the first const initialization must be executed (the slot
...@@ -4285,13 +4280,13 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { ...@@ -4285,13 +4280,13 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
JumpTarget slow_case(this); JumpTarget slow_case;
JumpTarget end(this); JumpTarget end;
JumpTarget not_a_flat_string(this); JumpTarget not_a_flat_string;
JumpTarget a_cons_string(this); JumpTarget a_cons_string;
JumpTarget try_again_with_new_string(this, JumpTarget::BIDIRECTIONAL); JumpTarget try_again_with_new_string(JumpTarget::BIDIRECTIONAL);
JumpTarget ascii_string(this); JumpTarget ascii_string;
JumpTarget got_char_code(this); JumpTarget got_char_code;
Load(args->at(0)); Load(args->at(0));
Load(args->at(1)); Load(args->at(1));
...@@ -4449,7 +4444,7 @@ void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { ...@@ -4449,7 +4444,7 @@ void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
JumpTarget leave(this); JumpTarget leave;
Load(args->at(0)); // Load the object. Load(args->at(0)); // Load the object.
frame_->Dup(); frame_->Dup();
Result object = frame_->Pop(); Result object = frame_->Pop();
...@@ -4473,7 +4468,7 @@ void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { ...@@ -4473,7 +4468,7 @@ void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2); ASSERT(args->length() == 2);
JumpTarget leave(this); JumpTarget leave;
Load(args->at(0)); // Load the object. Load(args->at(0)); // Load the object.
Load(args->at(1)); // Load the value. Load(args->at(1)); // Load the value.
Result value = frame_->Pop(); Result value = frame_->Pop();
...@@ -4702,8 +4697,8 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { ...@@ -4702,8 +4697,8 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
case Token::BIT_NOT: { case Token::BIT_NOT: {
// Smi check. // Smi check.
JumpTarget smi_label(this); JumpTarget smi_label;
JumpTarget continue_label(this); JumpTarget continue_label;
Result operand = frame_->Pop(); Result operand = frame_->Pop();
operand.ToRegister(); operand.ToRegister();
__ test(operand.reg(), Immediate(kSmiTagMask)); __ test(operand.reg(), Immediate(kSmiTagMask));
...@@ -4726,7 +4721,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { ...@@ -4726,7 +4721,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
case Token::ADD: { case Token::ADD: {
// Smi check. // Smi check.
JumpTarget continue_label(this); JumpTarget continue_label;
Result operand = frame_->Pop(); Result operand = frame_->Pop();
operand.ToRegister(); operand.ToRegister();
__ test(operand.reg(), Immediate(kSmiTagMask)); __ test(operand.reg(), Immediate(kSmiTagMask));
...@@ -4922,7 +4917,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -4922,7 +4917,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// is necessary because we assume that if we get control flow on the // is necessary because we assume that if we get control flow on the
// last path out of an expression we got it on all paths. // last path out of an expression we got it on all paths.
if (op == Token::AND) { if (op == Token::AND) {
JumpTarget is_true(this); JumpTarget is_true;
ControlDestination dest(&is_true, destination()->false_target(), true); ControlDestination dest(&is_true, destination()->false_target(), true);
LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false); LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false);
...@@ -4960,8 +4955,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -4960,8 +4955,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// We have a materialized value on the frame, so we exit with // We have a materialized value on the frame, so we exit with
// one on all paths. There are possibly also jumps to is_true // one on all paths. There are possibly also jumps to is_true
// from nested subexpressions. // from nested subexpressions.
JumpTarget pop_and_continue(this); JumpTarget pop_and_continue;
JumpTarget exit(this); JumpTarget exit;
// Avoid popping the result if it converts to 'false' using the // Avoid popping the result if it converts to 'false' using the
// standard ToBoolean() conversion as described in ECMA-262, // standard ToBoolean() conversion as described in ECMA-262,
...@@ -4985,7 +4980,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -4985,7 +4980,7 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
} }
} else if (op == Token::OR) { } else if (op == Token::OR) {
JumpTarget is_false(this); JumpTarget is_false;
ControlDestination dest(destination()->true_target(), &is_false, false); ControlDestination dest(destination()->true_target(), &is_false, false);
LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false); LoadCondition(node->left(), NOT_INSIDE_TYPEOF, &dest, false);
...@@ -5022,8 +5017,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { ...@@ -5022,8 +5017,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// We have a materialized value on the frame, so we exit with // We have a materialized value on the frame, so we exit with
// one on all paths. There are possibly also jumps to is_false // one on all paths. There are possibly also jumps to is_false
// from nested subexpressions. // from nested subexpressions.
JumpTarget pop_and_continue(this); JumpTarget pop_and_continue;
JumpTarget exit(this); JumpTarget exit;
// Avoid popping the result if it converts to 'true' using the // Avoid popping the result if it converts to 'true' using the
// standard ToBoolean() conversion as described in ECMA-262, // standard ToBoolean() conversion as described in ECMA-262,
...@@ -6010,7 +6005,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left, ...@@ -6010,7 +6005,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
// the left and right arguments, and jump to slow case. // the left and right arguments, and jump to slow case.
// The low bit of the left argument may be lost, but only // The low bit of the left argument may be lost, but only
// in a case where it is dropped anyway. // in a case where it is dropped anyway.
JumpTarget result_ok(generator()); JumpTarget result_ok;
__ test(left->reg(), Immediate(0xc0000000)); __ test(left->reg(), Immediate(0xc0000000));
result_ok.Branch(zero, left, taken); result_ok.Branch(zero, left, taken);
__ shl(left->reg()); __ shl(left->reg());
...@@ -6024,7 +6019,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left, ...@@ -6024,7 +6019,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
case Token::SHL: { case Token::SHL: {
__ shl(left->reg()); __ shl(left->reg());
// Check that the *signed* result fits in a smi. // Check that the *signed* result fits in a smi.
JumpTarget result_ok(generator()); JumpTarget result_ok;
__ cmp(left->reg(), 0xc0000000); __ cmp(left->reg(), 0xc0000000);
result_ok.Branch(positive, left, taken); result_ok.Branch(positive, left, taken);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "v8.h" #include "v8.h"
#include "codegen-inl.h" #include "codegen-inl.h"
#include "jump-target-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
namespace v8 { namespace internal { namespace v8 { namespace internal {
...@@ -35,42 +36,41 @@ namespace v8 { namespace internal { ...@@ -35,42 +36,41 @@ namespace v8 { namespace internal {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// JumpTarget implementation. // JumpTarget implementation.
#define __ ACCESS_MASM(masm_) #define __ ACCESS_MASM(cgen()->masm())
void JumpTarget::DoJump() { void JumpTarget::DoJump() {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
// Live non-frame registers are not allowed at unconditional jumps // Live non-frame registers are not allowed at unconditional jumps
// because we have no way of invalidating the corresponding results // because we have no way of invalidating the corresponding results
// which are still live in the C++ code. // which are still live in the C++ code.
ASSERT(cgen_->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
if (is_bound()) { if (is_bound()) {
// Backward jump. There is an expected frame to merge to. // Backward jump. There is an expected frame to merge to.
ASSERT(direction_ == BIDIRECTIONAL); ASSERT(direction_ == BIDIRECTIONAL);
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ jmp(&entry_label_); __ jmp(&entry_label_);
} else if (entry_frame_ != NULL) { } else if (entry_frame_ != NULL) {
// Forward jump with a preconfigured entry frame. Assert the // Forward jump with a preconfigured entry frame. Assert the
// current frame matches the expected one and jump to the block. // current frame matches the expected one and jump to the block.
ASSERT(cgen_->frame()->Equals(entry_frame_)); ASSERT(cgen()->frame()->Equals(entry_frame_));
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ jmp(&entry_label_); __ jmp(&entry_label_);
} else { } else {
// Forward jump. Remember the current frame and emit a jump to // Forward jump. Remember the current frame and emit a jump to
// its merge code. // its merge code.
AddReachingFrame(cgen_->frame()); AddReachingFrame(cgen()->frame());
RegisterFile empty; RegisterFile empty;
cgen_->SetFrame(NULL, &empty); cgen()->SetFrame(NULL, &empty);
__ jmp(&merge_labels_.last()); __ jmp(&merge_labels_.last());
} }
} }
void JumpTarget::DoBranch(Condition cc, Hint hint) { void JumpTarget::DoBranch(Condition cc, Hint hint) {
ASSERT(cgen_ != NULL); ASSERT(cgen() != NULL);
ASSERT(cgen_->has_valid_frame()); ASSERT(cgen()->has_valid_frame());
if (is_bound()) { if (is_bound()) {
ASSERT(direction_ == BIDIRECTIONAL); ASSERT(direction_ == BIDIRECTIONAL);
...@@ -80,29 +80,29 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) { ...@@ -80,29 +80,29 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) {
// Swap the current frame for a copy (we do the swapping to get // Swap the current frame for a copy (we do the swapping to get
// the off-frame registers off the fall through) to use for the // the off-frame registers off the fall through) to use for the
// branch. // branch.
VirtualFrame* fall_through_frame = cgen_->frame(); VirtualFrame* fall_through_frame = cgen()->frame();
VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame); VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame);
RegisterFile non_frame_registers = RegisterAllocator::Reserved(); RegisterFile non_frame_registers = RegisterAllocator::Reserved();
cgen_->SetFrame(branch_frame, &non_frame_registers); cgen()->SetFrame(branch_frame, &non_frame_registers);
// Check if we can avoid merge code. // Check if we can avoid merge code.
cgen_->frame()->PrepareMergeTo(entry_frame_); cgen()->frame()->PrepareMergeTo(entry_frame_);
if (cgen_->frame()->Equals(entry_frame_)) { if (cgen()->frame()->Equals(entry_frame_)) {
// Branch right in to the block. // Branch right in to the block.
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ j(cc, &entry_label_, hint); __ j(cc, &entry_label_, hint);
cgen_->SetFrame(fall_through_frame, &non_frame_registers); cgen()->SetFrame(fall_through_frame, &non_frame_registers);
return; return;
} }
// Check if we can reuse existing merge code. // Check if we can reuse existing merge code.
for (int i = 0; i < reaching_frames_.length(); i++) { for (int i = 0; i < reaching_frames_.length(); i++) {
if (reaching_frames_[i] != NULL && if (reaching_frames_[i] != NULL &&
cgen_->frame()->Equals(reaching_frames_[i])) { cgen()->frame()->Equals(reaching_frames_[i])) {
// Branch to the merge code. // Branch to the merge code.
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ j(cc, &merge_labels_[i], hint); __ j(cc, &merge_labels_[i], hint);
cgen_->SetFrame(fall_through_frame, &non_frame_registers); cgen()->SetFrame(fall_through_frame, &non_frame_registers);
return; return;
} }
} }
...@@ -111,21 +111,21 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) { ...@@ -111,21 +111,21 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) {
// around the merge code on the fall through path. // around the merge code on the fall through path.
Label original_fall_through; Label original_fall_through;
__ j(NegateCondition(cc), &original_fall_through, NegateHint(hint)); __ j(NegateCondition(cc), &original_fall_through, NegateHint(hint));
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ jmp(&entry_label_); __ jmp(&entry_label_);
cgen_->SetFrame(fall_through_frame, &non_frame_registers); cgen()->SetFrame(fall_through_frame, &non_frame_registers);
__ bind(&original_fall_through); __ bind(&original_fall_through);
} else if (entry_frame_ != NULL) { } else if (entry_frame_ != NULL) {
// Forward branch with a preconfigured entry frame. Assert the // Forward branch with a preconfigured entry frame. Assert the
// current frame matches the expected one and branch to the block. // current frame matches the expected one and branch to the block.
ASSERT(cgen_->frame()->Equals(entry_frame_)); ASSERT(cgen()->frame()->Equals(entry_frame_));
// Explicitly use the macro assembler instead of __ as forward // Explicitly use the macro assembler instead of __ as forward
// branches are expected to be a fixed size (no inserted // branches are expected to be a fixed size (no inserted
// coverage-checking instructions please). This is used in // coverage-checking instructions please). This is used in
// Reference::GetValue. // Reference::GetValue.
masm_->j(cc, &entry_label_, hint); cgen()->masm()->j(cc, &entry_label_, hint);
} else { } else {
// Forward branch. A copy of the current frame is remembered and // Forward branch. A copy of the current frame is remembered and
...@@ -133,8 +133,8 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) { ...@@ -133,8 +133,8 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) {
// macro assembler instead of __ as forward branches are expected // macro assembler instead of __ as forward branches are expected
// to be a fixed size (no inserted coverage-checking instructions // to be a fixed size (no inserted coverage-checking instructions
// please). This is used in Reference::GetValue. // please). This is used in Reference::GetValue.
AddReachingFrame(new VirtualFrame(cgen_->frame())); AddReachingFrame(new VirtualFrame(cgen()->frame()));
masm_->j(cc, &merge_labels_.last(), hint); cgen()->masm()->j(cc, &merge_labels_.last(), hint);
} }
} }
...@@ -146,14 +146,14 @@ void JumpTarget::Call() { ...@@ -146,14 +146,14 @@ void JumpTarget::Call() {
// at the label (which should be the only one) is the spilled current // at the label (which should be the only one) is the spilled current
// frame plus an in-memory return address. The "fall-through" frame // frame plus an in-memory return address. The "fall-through" frame
// at the return site is the spilled current frame. // at the return site is the spilled current frame.
ASSERT(cgen_ != NULL); ASSERT(cgen() != NULL);
ASSERT(cgen_->has_valid_frame()); ASSERT(cgen()->has_valid_frame());
// There are no non-frame references across the call. // There are no non-frame references across the call.
ASSERT(cgen_->HasValidEntryRegisters()); ASSERT(cgen()->HasValidEntryRegisters());
ASSERT(!is_linked()); ASSERT(!is_linked());
cgen_->frame()->SpillAll(); cgen()->frame()->SpillAll();
VirtualFrame* target_frame = new VirtualFrame(cgen_->frame()); VirtualFrame* target_frame = new VirtualFrame(cgen()->frame());
target_frame->Adjust(1); target_frame->Adjust(1);
// We do not expect a call with a preconfigured entry frame. // We do not expect a call with a preconfigured entry frame.
ASSERT(entry_frame_ == NULL); ASSERT(entry_frame_ == NULL);
...@@ -163,28 +163,28 @@ void JumpTarget::Call() { ...@@ -163,28 +163,28 @@ void JumpTarget::Call() {
void JumpTarget::DoBind(int mergable_elements) { void JumpTarget::DoBind(int mergable_elements) {
ASSERT(cgen_ != NULL); ASSERT(cgen() != NULL);
ASSERT(!is_bound()); ASSERT(!is_bound());
// Live non-frame registers are not allowed at the start of a basic // Live non-frame registers are not allowed at the start of a basic
// block. // block.
ASSERT(!cgen_->has_valid_frame() || cgen_->HasValidEntryRegisters()); ASSERT(!cgen()->has_valid_frame() || cgen()->HasValidEntryRegisters());
// Fast case: the jump target was manually configured with an entry // Fast case: the jump target was manually configured with an entry
// frame to use. // frame to use.
if (entry_frame_ != NULL) { if (entry_frame_ != NULL) {
// Assert no reaching frames to deal with. // Assert no reaching frames to deal with.
ASSERT(reaching_frames_.is_empty()); ASSERT(reaching_frames_.is_empty());
ASSERT(!cgen_->has_valid_frame()); ASSERT(!cgen()->has_valid_frame());
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile reserved = RegisterAllocator::Reserved();
if (direction_ == BIDIRECTIONAL) { if (direction_ == BIDIRECTIONAL) {
// Copy the entry frame so the original can be used for a // Copy the entry frame so the original can be used for a
// possible backward jump. // possible backward jump.
cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved); cgen()->SetFrame(new VirtualFrame(entry_frame_), &reserved);
} else { } else {
// Take ownership of the entry frame. // Take ownership of the entry frame.
cgen_->SetFrame(entry_frame_, &reserved); cgen()->SetFrame(entry_frame_, &reserved);
entry_frame_ = NULL; entry_frame_ = NULL;
} }
__ bind(&entry_label_); __ bind(&entry_label_);
...@@ -192,12 +192,12 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -192,12 +192,12 @@ void JumpTarget::DoBind(int mergable_elements) {
} }
if (!is_linked()) { if (!is_linked()) {
ASSERT(cgen_->has_valid_frame()); ASSERT(cgen()->has_valid_frame());
if (direction_ == FORWARD_ONLY) { if (direction_ == FORWARD_ONLY) {
// Fast case: no forward jumps and no possible backward jumps. // Fast case: no forward jumps and no possible backward jumps.
// The stack pointer can be floating above the top of the // The stack pointer can be floating above the top of the
// virtual frame before the bind. Afterward, it should not. // virtual frame before the bind. Afterward, it should not.
VirtualFrame* frame = cgen_->frame(); VirtualFrame* frame = cgen()->frame();
int difference = int difference =
frame->stack_pointer_ - (frame->elements_.length() - 1); frame->stack_pointer_ - (frame->elements_.length() - 1);
if (difference > 0) { if (difference > 0) {
...@@ -209,22 +209,22 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -209,22 +209,22 @@ void JumpTarget::DoBind(int mergable_elements) {
// Fast case: no forward jumps, possible backward ones. Remove // Fast case: no forward jumps, possible backward ones. Remove
// constants and copies above the watermark on the fall-through // constants and copies above the watermark on the fall-through
// frame and use it as the entry frame. // frame and use it as the entry frame.
cgen_->frame()->MakeMergable(mergable_elements); cgen()->frame()->MakeMergable(mergable_elements);
entry_frame_ = new VirtualFrame(cgen_->frame()); entry_frame_ = new VirtualFrame(cgen()->frame());
} }
__ bind(&entry_label_); __ bind(&entry_label_);
return; return;
} }
if (direction_ == FORWARD_ONLY && if (direction_ == FORWARD_ONLY &&
!cgen_->has_valid_frame() && !cgen()->has_valid_frame() &&
reaching_frames_.length() == 1) { reaching_frames_.length() == 1) {
// Fast case: no fall-through, a single forward jump, and no // Fast case: no fall-through, a single forward jump, and no
// possible backward jumps. Pick up the only reaching frame, take // possible backward jumps. Pick up the only reaching frame, take
// ownership of it, and use it for the block about to be emitted. // ownership of it, and use it for the block about to be emitted.
VirtualFrame* frame = reaching_frames_[0]; VirtualFrame* frame = reaching_frames_[0];
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &reserved);
reaching_frames_[0] = NULL; reaching_frames_[0] = NULL;
__ bind(&merge_labels_[0]); __ bind(&merge_labels_[0]);
...@@ -244,11 +244,11 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -244,11 +244,11 @@ void JumpTarget::DoBind(int mergable_elements) {
// If there is a current frame, record it as the fall-through. It // If there is a current frame, record it as the fall-through. It
// is owned by the reaching frames for now. // is owned by the reaching frames for now.
bool had_fall_through = false; bool had_fall_through = false;
if (cgen_->has_valid_frame()) { if (cgen()->has_valid_frame()) {
had_fall_through = true; had_fall_through = true;
AddReachingFrame(cgen_->frame()); // Return value ignored. AddReachingFrame(cgen()->frame()); // Return value ignored.
RegisterFile empty; RegisterFile empty;
cgen_->SetFrame(NULL, &empty); cgen()->SetFrame(NULL, &empty);
} }
// Compute the frame to use for entry to the block. // Compute the frame to use for entry to the block.
...@@ -283,17 +283,17 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -283,17 +283,17 @@ void JumpTarget::DoBind(int mergable_elements) {
// binding site or as the fall through from a previous merge // binding site or as the fall through from a previous merge
// code block. Jump around the code we are about to // code block. Jump around the code we are about to
// generate. // generate.
if (cgen_->has_valid_frame()) { if (cgen()->has_valid_frame()) {
cgen_->DeleteFrame(); cgen()->DeleteFrame();
__ jmp(&entry_label_); __ jmp(&entry_label_);
} }
// Pick up the frame for this block. Assume ownership if // Pick up the frame for this block. Assume ownership if
// there cannot be backward jumps. // there cannot be backward jumps.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile reserved = RegisterAllocator::Reserved();
if (direction_ == BIDIRECTIONAL) { if (direction_ == BIDIRECTIONAL) {
cgen_->SetFrame(new VirtualFrame(frame), &reserved); cgen()->SetFrame(new VirtualFrame(frame), &reserved);
} else { } else {
cgen_->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &reserved);
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
} }
__ bind(&merge_labels_[i]); __ bind(&merge_labels_[i]);
...@@ -302,7 +302,7 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -302,7 +302,7 @@ void JumpTarget::DoBind(int mergable_elements) {
// looking for any that can share merge code with this one. // looking for any that can share merge code with this one.
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
VirtualFrame* other = reaching_frames_[j]; VirtualFrame* other = reaching_frames_[j];
if (other != NULL && other->Equals(cgen_->frame())) { if (other != NULL && other->Equals(cgen()->frame())) {
// Set the reaching frame element to null to avoid // Set the reaching frame element to null to avoid
// processing it later, and then bind its entry label. // processing it later, and then bind its entry label.
reaching_frames_[j] = NULL; reaching_frames_[j] = NULL;
...@@ -311,13 +311,13 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -311,13 +311,13 @@ void JumpTarget::DoBind(int mergable_elements) {
} }
// Emit the merge code. // Emit the merge code.
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
} else if (i == reaching_frames_.length() - 1 && had_fall_through) { } else if (i == reaching_frames_.length() - 1 && had_fall_through) {
// If this is the fall through frame, and it didn't need // If this is the fall through frame, and it didn't need
// merge code, we need to pick up the frame so we can jump // merge code, we need to pick up the frame so we can jump
// around subsequent merge blocks if necessary. // around subsequent merge blocks if necessary.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &reserved);
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
} }
} }
...@@ -326,9 +326,9 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -326,9 +326,9 @@ void JumpTarget::DoBind(int mergable_elements) {
// The code generator may not have a current frame if there was no // The code generator may not have a current frame if there was no
// fall through and none of the reaching frames needed merging. // fall through and none of the reaching frames needed merging.
// In that case, clone the entry frame as the current frame. // In that case, clone the entry frame as the current frame.
if (!cgen_->has_valid_frame()) { if (!cgen()->has_valid_frame()) {
RegisterFile reserved_registers = RegisterAllocator::Reserved(); RegisterFile reserved_registers = RegisterAllocator::Reserved();
cgen_->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers); cgen()->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers);
} }
// There may be unprocessed reaching frames that did not need // There may be unprocessed reaching frames that did not need
...@@ -354,9 +354,9 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -354,9 +354,9 @@ void JumpTarget::DoBind(int mergable_elements) {
// Use a copy of the reaching frame so the original can be saved // Use a copy of the reaching frame so the original can be saved
// for possible reuse as a backward merge block. // for possible reuse as a backward merge block.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile reserved = RegisterAllocator::Reserved();
cgen_->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved); cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved);
__ bind(&merge_labels_[0]); __ bind(&merge_labels_[0]);
cgen_->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
} }
__ bind(&entry_label_); __ bind(&entry_label_);
......
...@@ -631,7 +631,7 @@ void MacroAssembler::NegativeZeroTest(CodeGenerator* cgen, ...@@ -631,7 +631,7 @@ void MacroAssembler::NegativeZeroTest(CodeGenerator* cgen,
Register result, Register result,
Register op, Register op,
JumpTarget* then_target) { JumpTarget* then_target) {
JumpTarget ok(cgen); JumpTarget ok;
test(result, Operand(result)); test(result, Operand(result));
ok.Branch(not_zero, taken); ok.Branch(not_zero, taken);
test(op, Operand(op)); test(op, Operand(op));
......
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
namespace v8 { namespace internal { namespace v8 { namespace internal {
CodeGenerator* JumpTarget::cgen() {
return CodeGeneratorScope::Current();
}
void JumpTarget::InitializeEntryElement(int index, FrameElement* target) { void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
entry_frame_->elements_[index].clear_copied(); entry_frame_->elements_[index].clear_copied();
if (target->is_register()) { if (target->is_register()) {
......
...@@ -39,36 +39,6 @@ namespace v8 { namespace internal { ...@@ -39,36 +39,6 @@ namespace v8 { namespace internal {
bool JumpTarget::compiling_deferred_code_ = false; bool JumpTarget::compiling_deferred_code_ = false;
JumpTarget::JumpTarget(CodeGenerator* cgen, Directionality direction)
: cgen_(cgen),
direction_(direction),
reaching_frames_(0),
merge_labels_(0),
entry_frame_(NULL) {
ASSERT(cgen != NULL);
masm_ = cgen->masm();
}
JumpTarget::JumpTarget()
: cgen_(NULL),
masm_(NULL),
direction_(FORWARD_ONLY),
reaching_frames_(0),
merge_labels_(0),
entry_frame_(NULL) {
}
void JumpTarget::Initialize(CodeGenerator* cgen, Directionality direction) {
ASSERT(cgen != NULL);
ASSERT(cgen_ == NULL);
cgen_ = cgen;
masm_ = cgen->masm();
direction_ = direction;
}
void JumpTarget::Unuse() { void JumpTarget::Unuse() {
reaching_frames_.Clear(); reaching_frames_.Clear();
merge_labels_.Clear(); merge_labels_.Clear();
...@@ -151,7 +121,7 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) { ...@@ -151,7 +121,7 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
// Build the new frame. A freshly allocated frame has memory elements // Build the new frame. A freshly allocated frame has memory elements
// for the parameters and some platform-dependent elements (e.g., // for the parameters and some platform-dependent elements (e.g.,
// return address). Replace those first. // return address). Replace those first.
entry_frame_ = new VirtualFrame(cgen_); entry_frame_ = new VirtualFrame(cgen());
int index = 0; int index = 0;
for (; index < entry_frame_->elements_.length(); index++) { for (; index < entry_frame_->elements_.length(); index++) {
FrameElement* target = elements[index]; FrameElement* target = elements[index];
...@@ -266,31 +236,28 @@ void JumpTarget::Jump() { ...@@ -266,31 +236,28 @@ void JumpTarget::Jump() {
void JumpTarget::Jump(Result* arg) { void JumpTarget::Jump(Result* arg) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
cgen_->frame()->Push(arg); cgen()->frame()->Push(arg);
DoJump(); DoJump();
} }
void JumpTarget::Jump(Result* arg0, Result* arg1) { void JumpTarget::Jump(Result* arg0, Result* arg1) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
cgen_->frame()->Push(arg0); cgen()->frame()->Push(arg0);
cgen_->frame()->Push(arg1); cgen()->frame()->Push(arg1);
DoJump(); DoJump();
} }
void JumpTarget::Jump(Result* arg0, Result* arg1, Result* arg2) { void JumpTarget::Jump(Result* arg0, Result* arg1, Result* arg2) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
cgen_->frame()->Push(arg0); cgen()->frame()->Push(arg0);
cgen_->frame()->Push(arg1); cgen()->frame()->Push(arg1);
cgen_->frame()->Push(arg2); cgen()->frame()->Push(arg2);
DoJump(); DoJump();
} }
...@@ -316,35 +283,33 @@ void JumpTarget::Branch(Condition cc, Hint hint) { ...@@ -316,35 +283,33 @@ void JumpTarget::Branch(Condition cc, Hint hint) {
#endif #endif
void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) { void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
// We want to check that non-frame registers at the call site stay in // We want to check that non-frame registers at the call site stay in
// the same registers on the fall-through branch. // the same registers on the fall-through branch.
DECLARE_ARGCHECK_VARS(arg); DECLARE_ARGCHECK_VARS(arg);
cgen_->frame()->Push(arg); cgen()->frame()->Push(arg);
DoBranch(cc, hint); DoBranch(cc, hint);
*arg = cgen_->frame()->Pop(); *arg = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg); ASSERT_ARGCHECK(arg);
} }
void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) { void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->frame() != NULL);
ASSERT(cgen_->frame() != NULL);
// We want to check that non-frame registers at the call site stay in // We want to check that non-frame registers at the call site stay in
// the same registers on the fall-through branch. // the same registers on the fall-through branch.
DECLARE_ARGCHECK_VARS(arg0); DECLARE_ARGCHECK_VARS(arg0);
DECLARE_ARGCHECK_VARS(arg1); DECLARE_ARGCHECK_VARS(arg1);
cgen_->frame()->Push(arg0); cgen()->frame()->Push(arg0);
cgen_->frame()->Push(arg1); cgen()->frame()->Push(arg1);
DoBranch(cc, hint); DoBranch(cc, hint);
*arg1 = cgen_->frame()->Pop(); *arg1 = cgen()->frame()->Pop();
*arg0 = cgen_->frame()->Pop(); *arg0 = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg0); ASSERT_ARGCHECK(arg0);
ASSERT_ARGCHECK(arg1); ASSERT_ARGCHECK(arg1);
...@@ -356,8 +321,7 @@ void JumpTarget::Branch(Condition cc, ...@@ -356,8 +321,7 @@ void JumpTarget::Branch(Condition cc,
Result* arg1, Result* arg1,
Result* arg2, Result* arg2,
Hint hint) { Hint hint) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->frame() != NULL);
ASSERT(cgen_->frame() != NULL);
// We want to check that non-frame registers at the call site stay in // We want to check that non-frame registers at the call site stay in
// the same registers on the fall-through branch. // the same registers on the fall-through branch.
...@@ -365,13 +329,13 @@ void JumpTarget::Branch(Condition cc, ...@@ -365,13 +329,13 @@ void JumpTarget::Branch(Condition cc,
DECLARE_ARGCHECK_VARS(arg1); DECLARE_ARGCHECK_VARS(arg1);
DECLARE_ARGCHECK_VARS(arg2); DECLARE_ARGCHECK_VARS(arg2);
cgen_->frame()->Push(arg0); cgen()->frame()->Push(arg0);
cgen_->frame()->Push(arg1); cgen()->frame()->Push(arg1);
cgen_->frame()->Push(arg2); cgen()->frame()->Push(arg2);
DoBranch(cc, hint); DoBranch(cc, hint);
*arg2 = cgen_->frame()->Pop(); *arg2 = cgen()->frame()->Pop();
*arg1 = cgen_->frame()->Pop(); *arg1 = cgen()->frame()->Pop();
*arg0 = cgen_->frame()->Pop(); *arg0 = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg0); ASSERT_ARGCHECK(arg0);
ASSERT_ARGCHECK(arg1); ASSERT_ARGCHECK(arg1);
...@@ -385,8 +349,7 @@ void JumpTarget::Branch(Condition cc, ...@@ -385,8 +349,7 @@ void JumpTarget::Branch(Condition cc,
Result* arg2, Result* arg2,
Result* arg3, Result* arg3,
Hint hint) { Hint hint) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->frame() != NULL);
ASSERT(cgen_->frame() != NULL);
// We want to check that non-frame registers at the call site stay in // We want to check that non-frame registers at the call site stay in
// the same registers on the fall-through branch. // the same registers on the fall-through branch.
...@@ -395,15 +358,15 @@ void JumpTarget::Branch(Condition cc, ...@@ -395,15 +358,15 @@ void JumpTarget::Branch(Condition cc,
DECLARE_ARGCHECK_VARS(arg2); DECLARE_ARGCHECK_VARS(arg2);
DECLARE_ARGCHECK_VARS(arg3); DECLARE_ARGCHECK_VARS(arg3);
cgen_->frame()->Push(arg0); cgen()->frame()->Push(arg0);
cgen_->frame()->Push(arg1); cgen()->frame()->Push(arg1);
cgen_->frame()->Push(arg2); cgen()->frame()->Push(arg2);
cgen_->frame()->Push(arg3); cgen()->frame()->Push(arg3);
DoBranch(cc, hint); DoBranch(cc, hint);
*arg3 = cgen_->frame()->Pop(); *arg3 = cgen()->frame()->Pop();
*arg2 = cgen_->frame()->Pop(); *arg2 = cgen()->frame()->Pop();
*arg1 = cgen_->frame()->Pop(); *arg1 = cgen()->frame()->Pop();
*arg0 = cgen_->frame()->Pop(); *arg0 = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg0); ASSERT_ARGCHECK(arg0);
ASSERT_ARGCHECK(arg1); ASSERT_ARGCHECK(arg1);
...@@ -413,15 +376,14 @@ void JumpTarget::Branch(Condition cc, ...@@ -413,15 +376,14 @@ void JumpTarget::Branch(Condition cc,
void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) { void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
int count = cgen_->frame()->height() - expected_height_; int count = cgen()->frame()->height() - expected_height_;
if (count > 0) { if (count > 0) {
// We negate and branch here rather than using DoBranch's negate // We negate and branch here rather than using DoBranch's negate
// and branch. This gives us a hook to remove statement state // and branch. This gives us a hook to remove statement state
// from the frame. // from the frame.
JumpTarget fall_through(cgen_); JumpTarget fall_through;
// Branch to fall through will not negate, because it is a // Branch to fall through will not negate, because it is a
// forward-only target. // forward-only target.
fall_through.Branch(NegateCondition(cc), NegateHint(hint)); fall_through.Branch(NegateCondition(cc), NegateHint(hint));
...@@ -429,9 +391,9 @@ void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) { ...@@ -429,9 +391,9 @@ void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
fall_through.Bind(); fall_through.Bind();
} else { } else {
DECLARE_ARGCHECK_VARS(arg); DECLARE_ARGCHECK_VARS(arg);
cgen_->frame()->Push(arg); cgen()->frame()->Push(arg);
DoBranch(cc, hint); DoBranch(cc, hint);
*arg = cgen_->frame()->Pop(); *arg = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg); ASSERT_ARGCHECK(arg);
} }
} }
...@@ -446,26 +408,22 @@ void JumpTarget::Bind(int mergable_elements) { ...@@ -446,26 +408,22 @@ void JumpTarget::Bind(int mergable_elements) {
void JumpTarget::Bind(Result* arg, int mergable_elements) { void JumpTarget::Bind(Result* arg, int mergable_elements) {
ASSERT(cgen_ != NULL); if (cgen()->has_valid_frame()) {
cgen()->frame()->Push(arg);
if (cgen_->has_valid_frame()) {
cgen_->frame()->Push(arg);
} }
DoBind(mergable_elements); DoBind(mergable_elements);
*arg = cgen_->frame()->Pop(); *arg = cgen()->frame()->Pop();
} }
void JumpTarget::Bind(Result* arg0, Result* arg1, int mergable_elements) { void JumpTarget::Bind(Result* arg0, Result* arg1, int mergable_elements) {
ASSERT(cgen_ != NULL); if (cgen()->has_valid_frame()) {
cgen()->frame()->Push(arg0);
if (cgen_->has_valid_frame()) { cgen()->frame()->Push(arg1);
cgen_->frame()->Push(arg0);
cgen_->frame()->Push(arg1);
} }
DoBind(mergable_elements); DoBind(mergable_elements);
*arg1 = cgen_->frame()->Pop(); *arg1 = cgen()->frame()->Pop();
*arg0 = cgen_->frame()->Pop(); *arg0 = cgen()->frame()->Pop();
} }
...@@ -473,17 +431,15 @@ void JumpTarget::Bind(Result* arg0, ...@@ -473,17 +431,15 @@ void JumpTarget::Bind(Result* arg0,
Result* arg1, Result* arg1,
Result* arg2, Result* arg2,
int mergable_elements) { int mergable_elements) {
ASSERT(cgen_ != NULL); if (cgen()->has_valid_frame()) {
cgen()->frame()->Push(arg0);
if (cgen_->has_valid_frame()) { cgen()->frame()->Push(arg1);
cgen_->frame()->Push(arg0); cgen()->frame()->Push(arg2);
cgen_->frame()->Push(arg1);
cgen_->frame()->Push(arg2);
} }
DoBind(mergable_elements); DoBind(mergable_elements);
*arg2 = cgen_->frame()->Pop(); *arg2 = cgen()->frame()->Pop();
*arg1 = cgen_->frame()->Pop(); *arg1 = cgen()->frame()->Pop();
*arg0 = cgen_->frame()->Pop(); *arg0 = cgen()->frame()->Pop();
} }
...@@ -492,19 +448,17 @@ void JumpTarget::Bind(Result* arg0, ...@@ -492,19 +448,17 @@ void JumpTarget::Bind(Result* arg0,
Result* arg2, Result* arg2,
Result* arg3, Result* arg3,
int mergable_elements) { int mergable_elements) {
ASSERT(cgen_ != NULL); if (cgen()->has_valid_frame()) {
cgen()->frame()->Push(arg0);
if (cgen_->has_valid_frame()) { cgen()->frame()->Push(arg1);
cgen_->frame()->Push(arg0); cgen()->frame()->Push(arg2);
cgen_->frame()->Push(arg1); cgen()->frame()->Push(arg3);
cgen_->frame()->Push(arg2);
cgen_->frame()->Push(arg3);
} }
DoBind(mergable_elements); DoBind(mergable_elements);
*arg3 = cgen_->frame()->Pop(); *arg3 = cgen()->frame()->Pop();
*arg2 = cgen_->frame()->Pop(); *arg2 = cgen()->frame()->Pop();
*arg1 = cgen_->frame()->Pop(); *arg1 = cgen()->frame()->Pop();
*arg0 = cgen_->frame()->Pop(); *arg0 = cgen()->frame()->Pop();
} }
...@@ -520,17 +474,15 @@ void JumpTarget::AddReachingFrame(VirtualFrame* frame) { ...@@ -520,17 +474,15 @@ void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// BreakTarget implementation. // BreakTarget implementation.
void BreakTarget::Initialize(CodeGenerator* cgen, Directionality direction) { void BreakTarget::set_direction(Directionality direction) {
JumpTarget::Initialize(cgen, direction); JumpTarget::set_direction(direction);
ASSERT(cgen_->has_valid_frame()); ASSERT(cgen()->has_valid_frame());
expected_height_ = cgen_->frame()->height(); expected_height_ = cgen()->frame()->height();
} }
void BreakTarget::CopyTo(BreakTarget* destination) { void BreakTarget::CopyTo(BreakTarget* destination) {
ASSERT(destination != NULL); ASSERT(destination != NULL);
destination->cgen_ = cgen_;
destination->masm_ = masm_;
destination->direction_ = direction_; destination->direction_ = direction_;
destination->reaching_frames_.Clear(); destination->reaching_frames_.Clear();
destination->merge_labels_.Clear(); destination->merge_labels_.Clear();
...@@ -546,36 +498,33 @@ void BreakTarget::CopyTo(BreakTarget* destination) { ...@@ -546,36 +498,33 @@ void BreakTarget::CopyTo(BreakTarget* destination) {
void BreakTarget::Jump() { void BreakTarget::Jump() {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
// Drop leftover statement state from the frame before merging. // Drop leftover statement state from the frame before merging.
cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_); cgen()->frame()->ForgetElements(cgen()->frame()->height() - expected_height_);
DoJump(); DoJump();
} }
void BreakTarget::Jump(Result* arg) { void BreakTarget::Jump(Result* arg) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
// Drop leftover statement state from the frame before merging. // Drop leftover statement state from the frame before merging.
cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_); cgen()->frame()->ForgetElements(cgen()->frame()->height() - expected_height_);
cgen_->frame()->Push(arg); cgen()->frame()->Push(arg);
DoJump(); DoJump();
} }
void BreakTarget::Branch(Condition cc, Hint hint) { void BreakTarget::Branch(Condition cc, Hint hint) {
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame());
int count = cgen_->frame()->height() - expected_height_; int count = cgen()->frame()->height() - expected_height_;
if (count > 0) { if (count > 0) {
// We negate and branch here rather than using DoBranch's negate // We negate and branch here rather than using DoBranch's negate
// and branch. This gives us a hook to remove statement state // and branch. This gives us a hook to remove statement state
// from the frame. // from the frame.
JumpTarget fall_through(cgen_); JumpTarget fall_through;
// Branch to fall through will not negate, because it is a // Branch to fall through will not negate, because it is a
// forward-only target. // forward-only target.
fall_through.Branch(NegateCondition(cc), NegateHint(hint)); fall_through.Branch(NegateCondition(cc), NegateHint(hint));
...@@ -589,7 +538,6 @@ void BreakTarget::Branch(Condition cc, Hint hint) { ...@@ -589,7 +538,6 @@ void BreakTarget::Branch(Condition cc, Hint hint) {
void BreakTarget::Bind(int mergable_elements) { void BreakTarget::Bind(int mergable_elements) {
#ifdef DEBUG #ifdef DEBUG
ASSERT(cgen_ != NULL);
// All the forward-reaching frames should have been adjusted at the // All the forward-reaching frames should have been adjusted at the
// jumps to this target. // jumps to this target.
for (int i = 0; i < reaching_frames_.length(); i++) { for (int i = 0; i < reaching_frames_.length(); i++) {
...@@ -600,8 +548,9 @@ void BreakTarget::Bind(int mergable_elements) { ...@@ -600,8 +548,9 @@ void BreakTarget::Bind(int mergable_elements) {
// Drop leftover statement state from the frame before merging, even // Drop leftover statement state from the frame before merging, even
// on the fall through. This is so we can bind the return target // on the fall through. This is so we can bind the return target
// with state on the frame. // with state on the frame.
if (cgen_->has_valid_frame()) { if (cgen()->has_valid_frame()) {
cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_); int count = cgen()->frame()->height() - expected_height_;
cgen()->frame()->ForgetElements(count);
} }
DoBind(mergable_elements); DoBind(mergable_elements);
} }
...@@ -609,7 +558,6 @@ void BreakTarget::Bind(int mergable_elements) { ...@@ -609,7 +558,6 @@ void BreakTarget::Bind(int mergable_elements) {
void BreakTarget::Bind(Result* arg, int mergable_elements) { void BreakTarget::Bind(Result* arg, int mergable_elements) {
#ifdef DEBUG #ifdef DEBUG
ASSERT(cgen_ != NULL);
// All the forward-reaching frames should have been adjusted at the // All the forward-reaching frames should have been adjusted at the
// jumps to this target. // jumps to this target.
for (int i = 0; i < reaching_frames_.length(); i++) { for (int i = 0; i < reaching_frames_.length(); i++) {
...@@ -620,12 +568,13 @@ void BreakTarget::Bind(Result* arg, int mergable_elements) { ...@@ -620,12 +568,13 @@ void BreakTarget::Bind(Result* arg, int mergable_elements) {
// Drop leftover statement state from the frame before merging, even // Drop leftover statement state from the frame before merging, even
// on the fall through. This is so we can bind the return target // on the fall through. This is so we can bind the return target
// with state on the frame. // with state on the frame.
if (cgen_->has_valid_frame()) { if (cgen()->has_valid_frame()) {
cgen_->frame()->ForgetElements(cgen_->frame()->height() - expected_height_); int count = cgen()->frame()->height() - expected_height_;
cgen_->frame()->Push(arg); cgen()->frame()->ForgetElements(count);
cgen()->frame()->Push(arg);
} }
DoBind(mergable_elements); DoBind(mergable_elements);
*arg = cgen_->frame()->Pop(); *arg = cgen()->frame()->Pop();
} }
...@@ -644,25 +593,14 @@ ShadowTarget::ShadowTarget(BreakTarget* shadowed) { ...@@ -644,25 +593,14 @@ ShadowTarget::ShadowTarget(BreakTarget* shadowed) {
// The original's state is reset. // The original's state is reset.
shadowed->Unuse(); shadowed->Unuse();
ASSERT(cgen_ != NULL); ASSERT(cgen()->has_valid_frame());
ASSERT(cgen_->has_valid_frame()); shadowed->set_expected_height(cgen()->frame()->height());
shadowed->set_expected_height(cgen_->frame()->height());
// Setting the code generator to null prevents the shadow target from
// being used until shadowing stops.
cgen_ = NULL;
masm_ = NULL;
} }
void ShadowTarget::StopShadowing() { void ShadowTarget::StopShadowing() {
ASSERT(is_shadowing_); ASSERT(is_shadowing_);
// This target does not have a valid code generator yet.
cgen_ = other_target_->code_generator();
ASSERT(cgen_ != NULL);
masm_ = cgen_->masm();
// The states of this target, which was shadowed, and the original // The states of this target, which was shadowed, and the original
// target, which was shadowing, are swapped. // target, which was shadowing, are swapped.
BreakTarget temp; BreakTarget temp;
......
...@@ -56,31 +56,34 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated. ...@@ -56,31 +56,34 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
// Forward-only jump targets can only be reached by forward CFG edges. // Forward-only jump targets can only be reached by forward CFG edges.
enum Directionality { FORWARD_ONLY, BIDIRECTIONAL }; enum Directionality { FORWARD_ONLY, BIDIRECTIONAL };
// Construct a jump target with a given code generator used to generate // Construct a jump target used to generate code and to provide
// code and to provide access to a current frame. // access to a current frame.
explicit JumpTarget(CodeGenerator* cgen, explicit JumpTarget(Directionality direction)
Directionality direction = FORWARD_ONLY); : direction_(direction),
reaching_frames_(0),
merge_labels_(0),
entry_frame_(NULL) {
}
// Construct a jump target without a code generator. A code // Construct a jump target.
// generator must be supplied before using the jump target as a JumpTarget()
// label. This is useful, eg, when break targets are embedded in : direction_(FORWARD_ONLY),
// AST nodes. reaching_frames_(0),
JumpTarget(); merge_labels_(0),
entry_frame_(NULL) {
}
virtual ~JumpTarget() {} virtual ~JumpTarget() {}
// Supply a code generator and directionality to an already // Set the direction of the jump target.
// constructed jump target. This function expects to be given a virtual void set_direction(Directionality direction) {
// non-null code generator, and to be called only when the code direction_ = direction;
// generator is not yet set. }
virtual void Initialize(CodeGenerator* cgen,
Directionality direction = FORWARD_ONLY);
// Treat the jump target as a fresh one. The state is reset. // Treat the jump target as a fresh one. The state is reset.
void Unuse(); void Unuse();
// Accessors. inline CodeGenerator* cgen();
CodeGenerator* code_generator() const { return cgen_; }
Label* entry_label() { return &entry_label_; } Label* entry_label() { return &entry_label_; }
...@@ -163,12 +166,6 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated. ...@@ -163,12 +166,6 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
} }
protected: protected:
// The code generator gives access to its current frame.
CodeGenerator* cgen_;
// Used to emit code.
MacroAssembler* masm_;
// Directionality flag set at initialization time. // Directionality flag set at initialization time.
Directionality direction_; Directionality direction_;
...@@ -224,20 +221,13 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated. ...@@ -224,20 +221,13 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
class BreakTarget : public JumpTarget { class BreakTarget : public JumpTarget {
public: public:
// Construct a break target without a code generator. A code // Construct a break target.
// generator must be supplied before using the break target as a
// label. This is useful, eg, when break targets are embedded in AST
// nodes.
BreakTarget() {} BreakTarget() {}
virtual ~BreakTarget() {} virtual ~BreakTarget() {}
// Supply a code generator, expected expression stack height, and // Set the direction of the break target.
// directionality to an already constructed break target. This virtual void set_direction(Directionality direction);
// function expects to be given a non-null code generator, and to be
// called only when the code generator is not yet set.
virtual void Initialize(CodeGenerator* cgen,
Directionality direction = FORWARD_ONLY);
// Copy the state of this break target to the destination. The // Copy the state of this break target to the destination. The
// lists of forward-reaching frames and merge-point labels are // lists of forward-reaching frames and merge-point labels are
......
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