| Index: src/full-codegen.cc
|
| ===================================================================
|
| --- src/full-codegen.cc (revision 5450)
|
| +++ src/full-codegen.cc (working copy)
|
| @@ -336,33 +336,123 @@
|
| }
|
|
|
|
|
| -void FullCodeGenerator::PrepareTest(Label* materialize_true,
|
| - Label* materialize_false,
|
| - Label** if_true,
|
| - Label** if_false,
|
| - Label** fall_through) {
|
| - switch (context_) {
|
| - case Expression::kUninitialized:
|
| - UNREACHABLE();
|
| - break;
|
| - case Expression::kEffect:
|
| - // In an effect context, the true and the false case branch to the
|
| - // same label.
|
| - *if_true = *if_false = *fall_through = materialize_true;
|
| - break;
|
| - case Expression::kValue:
|
| - *if_true = *fall_through = materialize_true;
|
| - *if_false = materialize_false;
|
| - break;
|
| - case Expression::kTest:
|
| - *if_true = true_label_;
|
| - *if_false = false_label_;
|
| - *fall_through = fall_through_;
|
| - break;
|
| - }
|
| +void FullCodeGenerator::EffectContext::DropAndPlug(int count,
|
| + Register reg) const {
|
| + ASSERT(count > 0);
|
| + __ Drop(count);
|
| }
|
|
|
|
|
| +void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
|
| + int count,
|
| + Register reg) const {
|
| + ASSERT(count > 0);
|
| + __ Drop(count);
|
| + __ Move(result_register(), reg);
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::TestContext::DropAndPlug(int count,
|
| + Register reg) const {
|
| + ASSERT(count > 0);
|
| + // For simplicity we always test the accumulator register.
|
| + __ Drop(count);
|
| + __ Move(result_register(), reg);
|
| + codegen()->DoTest(true_label_, false_label_, fall_through_);
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::EffectContext::Plug(Register reg) const {
|
| + // Nothing to do.
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
|
| + // Move value into place.
|
| + __ Move(result_register(), reg);
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
|
| + // Move value into place.
|
| + __ push(reg);
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::TestContext::Plug(Register reg) const {
|
| + // For simplicity we always test the accumulator register.
|
| + __ Move(result_register(), reg);
|
| + codegen()->DoTest(true_label_, false_label_, fall_through_);
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::EffectContext::PlugTOS() const {
|
| + __ Drop(1);
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
|
| + __ pop(result_register());
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::StackValueContext::PlugTOS() const {
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::TestContext::PlugTOS() const {
|
| + // For simplicity we always test the accumulator register.
|
| + __ pop(result_register());
|
| + codegen()->DoTest(true_label_, false_label_, fall_through_);
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::EffectContext::PrepareTest(
|
| + Label* materialize_true,
|
| + Label* materialize_false,
|
| + Label** if_true,
|
| + Label** if_false,
|
| + Label** fall_through) const {
|
| + // In an effect context, the true and the false case branch to the
|
| + // same label.
|
| + *if_true = *if_false = *fall_through = materialize_true;
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
|
| + Label* materialize_true,
|
| + Label* materialize_false,
|
| + Label** if_true,
|
| + Label** if_false,
|
| + Label** fall_through) const {
|
| + *if_true = *fall_through = materialize_true;
|
| + *if_false = materialize_false;
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::StackValueContext::PrepareTest(
|
| + Label* materialize_true,
|
| + Label* materialize_false,
|
| + Label** if_true,
|
| + Label** if_false,
|
| + Label** fall_through) const {
|
| + *if_true = *fall_through = materialize_true;
|
| + *if_false = materialize_false;
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::TestContext::PrepareTest(
|
| + Label* materialize_true,
|
| + Label* materialize_false,
|
| + Label** if_true,
|
| + Label** if_false,
|
| + Label** fall_through) const {
|
| + *if_true = true_label_;
|
| + *if_false = false_label_;
|
| + *fall_through = fall_through_;
|
| +}
|
| +
|
| +
|
| void FullCodeGenerator::VisitDeclarations(
|
| ZoneList<Declaration*>* declarations) {
|
| int length = declarations->length();
|
| @@ -562,20 +652,20 @@
|
|
|
| // Load only the operands that we need to materialize.
|
| if (constant == kNoConstants) {
|
| - VisitForValue(left, kStack);
|
| - VisitForValue(right, kAccumulator);
|
| + VisitForStackValue(left);
|
| + VisitForAccumulatorValue(right);
|
| } else if (constant == kRightConstant) {
|
| - VisitForValue(left, kAccumulator);
|
| + VisitForAccumulatorValue(left);
|
| } else {
|
| ASSERT(constant == kLeftConstant);
|
| - VisitForValue(right, kAccumulator);
|
| + VisitForAccumulatorValue(right);
|
| }
|
|
|
| SetSourcePosition(expr->position());
|
| if (ShouldInlineSmiCase(op)) {
|
| - EmitInlineSmiBinaryOp(expr, op, context_, mode, left, right, constant);
|
| + EmitInlineSmiBinaryOp(expr, op, mode, left, right, constant);
|
| } else {
|
| - EmitBinaryOp(op, context_, mode);
|
| + EmitBinaryOp(op, mode);
|
| }
|
| break;
|
| }
|
| @@ -589,39 +679,7 @@
|
| void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
|
| Label eval_right, done;
|
|
|
| - // Set up the appropriate context for the left subexpression based
|
| - // on the operation and our own context. Initially assume we can
|
| - // inherit both true and false labels from our context.
|
| - if (expr->op() == Token::OR) {
|
| - switch (context_) {
|
| - case Expression::kUninitialized:
|
| - UNREACHABLE();
|
| - case Expression::kEffect:
|
| - VisitForControl(expr->left(), &done, &eval_right, &eval_right);
|
| - break;
|
| - case Expression::kValue:
|
| - VisitLogicalForValue(expr->left(), expr->op(), location_, &done);
|
| - break;
|
| - case Expression::kTest:
|
| - VisitForControl(expr->left(), true_label_, &eval_right, &eval_right);
|
| - break;
|
| - }
|
| - } else {
|
| - ASSERT_EQ(Token::AND, expr->op());
|
| - switch (context_) {
|
| - case Expression::kUninitialized:
|
| - UNREACHABLE();
|
| - case Expression::kEffect:
|
| - VisitForControl(expr->left(), &eval_right, &done, &eval_right);
|
| - break;
|
| - case Expression::kValue:
|
| - VisitLogicalForValue(expr->left(), expr->op(), location_, &done);
|
| - break;
|
| - case Expression::kTest:
|
| - VisitForControl(expr->left(), &eval_right, false_label_, &eval_right);
|
| - break;
|
| - }
|
| - }
|
| + context()->EmitLogicalLeft(expr, &eval_right, &done);
|
|
|
| __ bind(&eval_right);
|
| Visit(expr->right());
|
| @@ -630,43 +688,75 @@
|
| }
|
|
|
|
|
| -void FullCodeGenerator::VisitLogicalForValue(Expression* expr,
|
| - Token::Value op,
|
| - Location where,
|
| - Label* done) {
|
| - ASSERT(op == Token::AND || op == Token::OR);
|
| - VisitForValue(expr, kAccumulator);
|
| +// Set up the appropriate context for the left subexpression based
|
| +// on the operation and our own context. Initially assume we can
|
| +// inherit both true and false labels from our context.
|
| +
|
| +void FullCodeGenerator::EffectContext::EmitLogicalLeft(BinaryOperation* expr,
|
| + Label* eval_right,
|
| + Label* done) const {
|
| + if (expr->op() == Token::OR) {
|
| + codegen()->VisitForControl(expr->left(), done, eval_right, eval_right);
|
| + } else {
|
| + ASSERT(expr->op() == Token::AND);
|
| + codegen()->VisitForControl(expr->left(), eval_right, done, eval_right);
|
| + }
|
| +}
|
| +
|
| +
|
| +void FullCodeGenerator::AccumulatorValueContext::EmitLogicalLeft(
|
| + BinaryOperation* expr,
|
| + Label* eval_right,
|
| + Label* done) const {
|
| + codegen()->Visit(expr->left());
|
| __ push(result_register());
|
| + Label discard, restore;
|
| + if (expr->op() == Token::OR) {
|
| + codegen()->DoTest(&restore, &discard, &restore);
|
| + } else {
|
| + ASSERT(expr->op() == Token::AND);
|
| + codegen()->DoTest(&discard, &restore, &restore);
|
| + }
|
| + __ bind(&restore);
|
| + __ pop(result_register());
|
| + __ jmp(done);
|
| + __ bind(&discard);
|
| + __ Drop(1);
|
| +}
|
|
|
| +
|
| +void FullCodeGenerator::StackValueContext::EmitLogicalLeft(
|
| + BinaryOperation* expr,
|
| + Label* eval_right,
|
| + Label* done) const {
|
| + codegen()->VisitForAccumulatorValue(expr->left());
|
| + __ push(result_register());
|
| Label discard;
|
| - switch (where) {
|
| - case kAccumulator: {
|
| - Label restore;
|
| - if (op == Token::OR) {
|
| - DoTest(&restore, &discard, &restore);
|
| - } else {
|
| - DoTest(&discard, &restore, &restore);
|
| - }
|
| - __ bind(&restore);
|
| - __ pop(result_register());
|
| - __ jmp(done);
|
| - break;
|
| - }
|
| - case kStack: {
|
| - if (op == Token::OR) {
|
| - DoTest(done, &discard, &discard);
|
| - } else {
|
| - DoTest(&discard, done, &discard);
|
| - }
|
| - break;
|
| - }
|
| + if (expr->op() == Token::OR) {
|
| + codegen()->DoTest(done, &discard, &discard);
|
| + } else {
|
| + ASSERT(expr->op() == Token::AND);
|
| + codegen()->DoTest(&discard, done, &discard);
|
| }
|
| -
|
| __ bind(&discard);
|
| __ Drop(1);
|
| }
|
|
|
|
|
| +void FullCodeGenerator::TestContext::EmitLogicalLeft(BinaryOperation* expr,
|
| + Label* eval_right,
|
| + Label* done) const {
|
| + if (expr->op() == Token::OR) {
|
| + codegen()->VisitForControl(expr->left(),
|
| + true_label_, eval_right, eval_right);
|
| + } else {
|
| + ASSERT(expr->op() == Token::AND);
|
| + codegen()->VisitForControl(expr->left(),
|
| + eval_right, false_label_, eval_right);
|
| + }
|
| +}
|
| +
|
| +
|
| void FullCodeGenerator::VisitBlock(Block* stmt) {
|
| Comment cmnt(masm_, "[ Block");
|
| Breakable nested_statement(this, stmt);
|
| @@ -747,7 +837,7 @@
|
| Comment cmnt(masm_, "[ ReturnStatement");
|
| SetStatementPosition(stmt);
|
| Expression* expr = stmt->expression();
|
| - VisitForValue(expr, kAccumulator);
|
| + VisitForAccumulatorValue(expr);
|
|
|
| // Exit all nested statements.
|
| NestedStatement* current = nesting_stack_;
|
| @@ -766,7 +856,7 @@
|
| Comment cmnt(masm_, "[ WithEnterStatement");
|
| SetStatementPosition(stmt);
|
|
|
| - VisitForValue(stmt->expression(), kStack);
|
| + VisitForStackValue(stmt->expression());
|
| if (stmt->is_catch_block()) {
|
| __ CallRuntime(Runtime::kPushCatchContext, 1);
|
| } else {
|
| @@ -1047,7 +1137,7 @@
|
| expr->then_expression_position());
|
| Visit(expr->then_expression());
|
| // If control flow falls through Visit, jump to done.
|
| - if (context_ == Expression::kEffect || context_ == Expression::kValue) {
|
| + if (!context()->IsTest()) {
|
| __ jmp(&done);
|
| }
|
|
|
| @@ -1056,7 +1146,7 @@
|
| expr->else_expression_position());
|
| Visit(expr->else_expression());
|
| // If control flow falls through Visit, merge it with true case here.
|
| - if (context_ == Expression::kEffect || context_ == Expression::kValue) {
|
| + if (!context()->IsTest()) {
|
| __ bind(&done);
|
| }
|
| }
|
| @@ -1070,7 +1160,7 @@
|
|
|
| void FullCodeGenerator::VisitLiteral(Literal* expr) {
|
| Comment cmnt(masm_, "[ Literal");
|
| - Apply(context_, expr);
|
| + context()->Plug(expr->handle());
|
| }
|
|
|
|
|
| @@ -1096,17 +1186,17 @@
|
| // Call runtime routine to allocate the catch extension object and
|
| // assign the exception value to the catch variable.
|
| Comment cmnt(masm_, "[ CatchExtensionObject");
|
| - VisitForValue(expr->key(), kStack);
|
| - VisitForValue(expr->value(), kStack);
|
| + VisitForStackValue(expr->key());
|
| + VisitForStackValue(expr->value());
|
| // Create catch extension object.
|
| __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
|
| - Apply(context_, result_register());
|
| + context()->Plug(result_register());
|
| }
|
|
|
|
|
| void FullCodeGenerator::VisitThrow(Throw* expr) {
|
| Comment cmnt(masm_, "[ Throw");
|
| - VisitForValue(expr->exception(), kStack);
|
| + VisitForStackValue(expr->exception());
|
| __ CallRuntime(Runtime::kThrow, 1);
|
| // Never returns here.
|
| }
|
| @@ -1136,9 +1226,9 @@
|
|
|
| void FullCodeGenerator::EmitRegExpCloneResult(ZoneList<Expression*>* args) {
|
| ASSERT(args->length() == 1);
|
| - VisitForValue(args->at(0), kStack);
|
| + VisitForStackValue(args->at(0));
|
| __ CallRuntime(Runtime::kRegExpCloneResult, 1);
|
| - Apply(context_, result_register());
|
| + context()->Plug(result_register());
|
| }
|
|
|
| #undef __
|
|
|