Chromium Code Reviews| Index: src/full-codegen.cc |
| =================================================================== |
| --- src/full-codegen.cc (revision 8079) |
| +++ src/full-codegen.cc (working copy) |
| @@ -702,143 +702,110 @@ |
| void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| Comment cmnt(masm_, "[ BinaryOperation"); |
|
Kevin Millikin (Chromium)
2011/05/31 11:46:28
By moving this comment into VisitComma, VisitLogic
Sven Panne
2011/05/31 14:30:33
Done.
|
| + switch (expr->op()) { |
| + case Token::COMMA: return VisitComma(expr); |
| + case Token::OR: return VisitAndOr(expr, false); |
|
Kevin Millikin (Chromium)
2011/05/31 11:46:28
Let's not pass the flag here, since we can just us
Sven Panne
2011/05/31 14:30:33
Done, same for HGraphBuilder.
|
| + case Token::AND: return VisitAndOr(expr, true); |
| + default: return VisitCommon(expr); |
| + } |
| +} |
| + |
| + |
| +void FullCodeGenerator::VisitCommon(BinaryOperation* expr) { |
| Token::Value op = expr->op(); |
| Expression* left = expr->left(); |
| Expression* right = expr->right(); |
| + OverwriteMode mode = |
| + left->ResultOverwriteAllowed() |
| + ? OVERWRITE_LEFT |
| + : (right->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE); |
| - OverwriteMode mode = NO_OVERWRITE; |
| - if (left->ResultOverwriteAllowed()) { |
| - mode = OVERWRITE_LEFT; |
| - } else if (right->ResultOverwriteAllowed()) { |
| - mode = OVERWRITE_RIGHT; |
| - } |
| + VisitForStackValue(left); |
| + VisitForAccumulatorValue(right); |
| - switch (op) { |
| - case Token::COMMA: |
| - VisitForEffect(left); |
| - if (context()->IsTest()) ForwardBailoutToChild(expr); |
| - context()->HandleExpression(right); |
| - break; |
| - |
| - case Token::OR: |
| - case Token::AND: |
| - EmitLogicalOperation(expr); |
| - break; |
| - |
| - case Token::ADD: |
| - case Token::SUB: |
| - case Token::DIV: |
| - case Token::MOD: |
| - case Token::MUL: |
| - case Token::BIT_OR: |
| - case Token::BIT_AND: |
| - case Token::BIT_XOR: |
| - case Token::SHL: |
| - case Token::SHR: |
| - case Token::SAR: { |
| - // Load both operands. |
| - VisitForStackValue(left); |
| - VisitForAccumulatorValue(right); |
| - |
| - SetSourcePosition(expr->position()); |
| - if (ShouldInlineSmiCase(op)) { |
| - EmitInlineSmiBinaryOp(expr, op, mode, left, right); |
| - } else { |
| - EmitBinaryOp(expr, op, mode); |
| - } |
| - break; |
| - } |
| - |
| - default: |
| - UNREACHABLE(); |
| + SetSourcePosition(expr->position()); |
| + if (ShouldInlineSmiCase(op)) { |
| + EmitInlineSmiBinaryOp(expr, op, mode, left, right); |
| + } else { |
| + EmitBinaryOp(expr, op, mode); |
| } |
| } |
| -void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { |
| - Label eval_right, done; |
| - |
| - context()->EmitLogicalLeft(expr, &eval_right, &done); |
| - |
| - PrepareForBailoutForId(expr->RightId(), NO_REGISTERS); |
| - __ bind(&eval_right); |
| +void FullCodeGenerator::VisitComma(BinaryOperation* expr) { |
| + VisitForEffect(expr->left()); |
| if (context()->IsTest()) ForwardBailoutToChild(expr); |
| - context()->HandleExpression(expr->right()); |
| - |
| - __ bind(&done); |
| + VisitInSameContext(expr->right()); |
| } |
| -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::VisitAndOr(BinaryOperation* expr, bool is_logical_and) { |
| + Expression* left = expr->left(); |
| + Expression* right = expr->right(); |
| + int rightId = expr->RightId(); |
|
Kevin Millikin (Chromium)
2011/05/31 11:46:28
right_id
Sven Panne
2011/05/31 14:30:33
Done.
|
| + Label done; |
| + if (context()->IsTest()) { |
|
Kevin Millikin (Chromium)
2011/05/31 11:46:28
I did like having this code as virtual functions o
Sven Panne
2011/05/31 14:30:33
In principle I agree that the explicit IfFooContex
|
| + Label eval_right; |
| + const TestContext* test = TestContext::cast(context()); |
| + if (is_logical_and) { |
| + VisitForControl(left, &eval_right, test->false_label(), &eval_right); |
| + } else { |
| + VisitForControl(left, test->true_label(), &eval_right, &eval_right); |
| + } |
| + PrepareForBailoutForId(rightId, NO_REGISTERS); |
| + __ bind(&eval_right); |
| + ForwardBailoutToChild(expr); |
| -void FullCodeGenerator::AccumulatorValueContext::EmitLogicalLeft( |
| - BinaryOperation* expr, |
| - Label* eval_right, |
| - Label* done) const { |
| - HandleExpression(expr->left()); |
| - // We want the value in the accumulator for the test, and on the stack in case |
| - // we need it. |
| - __ push(result_register()); |
| - Label discard, restore; |
| - if (expr->op() == Token::OR) { |
| - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| - codegen()->DoTest(&restore, &discard, &restore); |
| - } else { |
| - ASSERT(expr->op() == Token::AND); |
| - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| - codegen()->DoTest(&discard, &restore, &restore); |
| - } |
| - __ bind(&restore); |
| - __ pop(result_register()); |
| - __ jmp(done); |
| - __ bind(&discard); |
| - __ Drop(1); |
| -} |
| + } else if (context()->IsAccumulatorValue()) { |
| + VisitForAccumulatorValue(left); |
| + // We want the value in the accumulator for the test, and on the stack in |
| + // case we need it. |
| + __ push(result_register()); |
| + Label discard, restore; |
| + PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| + if (is_logical_and) { |
| + DoTest(&discard, &restore, &restore); |
| + } else { |
| + DoTest(&restore, &discard, &restore); |
| + } |
| + __ bind(&restore); |
| + __ pop(result_register()); |
| + __ jmp(&done); |
| + __ bind(&discard); |
| + __ Drop(1); |
| + PrepareForBailoutForId(rightId, NO_REGISTERS); |
| + } else if (context()->IsStackValue()) { |
| + VisitForAccumulatorValue(left); |
| + // We want the value in the accumulator for the test, and on the stack in |
| + // case we need it. |
| + __ push(result_register()); |
| + Label discard; |
| + PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| + if (is_logical_and) { |
| + DoTest(&discard, &done, &discard); |
| + } else { |
| + DoTest(&done, &discard, &discard); |
| + } |
| + __ bind(&discard); |
| + __ Drop(1); |
| + PrepareForBailoutForId(rightId, NO_REGISTERS); |
| -void FullCodeGenerator::StackValueContext::EmitLogicalLeft( |
| - BinaryOperation* expr, |
| - Label* eval_right, |
| - Label* done) const { |
| - codegen()->VisitForAccumulatorValue(expr->left()); |
| - // We want the value in the accumulator for the test, and on the stack in case |
| - // we need it. |
| - __ push(result_register()); |
| - Label discard; |
| - if (expr->op() == Token::OR) { |
| - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| - codegen()->DoTest(done, &discard, &discard); |
| } else { |
| - ASSERT(expr->op() == Token::AND); |
| - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); |
| - codegen()->DoTest(&discard, done, &discard); |
| + ASSERT(context()->IsEffect()); |
| + Label eval_right; |
| + if (is_logical_and) { |
| + VisitForControl(left, &eval_right, &done, &eval_right); |
| + } else { |
| + VisitForControl(left, &done, &eval_right, &eval_right); |
| + } |
| + PrepareForBailoutForId(rightId, NO_REGISTERS); |
| + __ bind(&eval_right); |
| } |
| - __ 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); |
| - } |
| + VisitInSameContext(right); |
| + __ bind(&done); |
| } |
| @@ -850,49 +817,26 @@ |
| } |
| -void FullCodeGenerator::EffectContext::HandleExpression( |
| - Expression* expr) const { |
| - codegen()->HandleInNonTestContext(expr, NO_REGISTERS); |
| +void FullCodeGenerator::VisitInSameContext(Expression* expr) { |
| + if (context()->IsTest()) { |
| + ForwardBailoutStack stack(expr, forward_bailout_pending_); |
| + ForwardBailoutStack* saved = forward_bailout_stack_; |
| + forward_bailout_pending_ = NULL; |
| + forward_bailout_stack_ = &stack; |
| + AstVisitor::Visit(expr); |
|
Kevin Millikin (Chromium)
2011/05/31 11:46:28
This can just be Visit(expr), can't it?
Sven Panne
2011/05/31 14:30:33
Done.
|
| + forward_bailout_stack_ = saved; |
| + } else { |
| + ASSERT(forward_bailout_pending_ == NULL); |
| + Visit(expr); |
| + State state = context()->IsAccumulatorValue() ? TOS_REG : NO_REGISTERS; |
| + PrepareForBailout(expr, state); |
| + // Forwarding bailouts to children is a one shot operation. It should have |
| + // been processed at this point. |
| + ASSERT(forward_bailout_pending_ == NULL); |
| + } |
| } |
| -void FullCodeGenerator::AccumulatorValueContext::HandleExpression( |
| - Expression* expr) const { |
| - codegen()->HandleInNonTestContext(expr, TOS_REG); |
| -} |
| - |
| - |
| -void FullCodeGenerator::StackValueContext::HandleExpression( |
| - Expression* expr) const { |
| - codegen()->HandleInNonTestContext(expr, NO_REGISTERS); |
| -} |
| - |
| - |
| -void FullCodeGenerator::TestContext::HandleExpression(Expression* expr) const { |
| - codegen()->VisitInTestContext(expr); |
| -} |
| - |
| - |
| -void FullCodeGenerator::HandleInNonTestContext(Expression* expr, State state) { |
| - ASSERT(forward_bailout_pending_ == NULL); |
| - AstVisitor::Visit(expr); |
| - PrepareForBailout(expr, state); |
| - // Forwarding bailouts to children is a one shot operation. It |
| - // should have been processed at this point. |
| - ASSERT(forward_bailout_pending_ == NULL); |
| -} |
| - |
| - |
| -void FullCodeGenerator::VisitInTestContext(Expression* expr) { |
| - ForwardBailoutStack stack(expr, forward_bailout_pending_); |
| - ForwardBailoutStack* saved = forward_bailout_stack_; |
| - forward_bailout_pending_ = NULL; |
| - forward_bailout_stack_ = &stack; |
| - AstVisitor::Visit(expr); |
| - forward_bailout_stack_ = saved; |
| -} |
| - |
| - |
| void FullCodeGenerator::VisitBlock(Block* stmt) { |
| Comment cmnt(masm_, "[ Block"); |
| Breakable nested_statement(this, stmt); |
| @@ -1287,7 +1231,7 @@ |
| for_test->false_label(), |
| NULL); |
| } else { |
| - context()->HandleExpression(expr->then_expression()); |
| + VisitInSameContext(expr->then_expression()); |
| __ jmp(&done); |
| } |
| @@ -1296,7 +1240,7 @@ |
| if (context()->IsTest()) ForwardBailoutToChild(expr); |
| SetExpressionPosition(expr->else_expression(), |
| expr->else_expression_position()); |
| - context()->HandleExpression(expr->else_expression()); |
| + VisitInSameContext(expr->else_expression()); |
| // If control flow falls through Visit, merge it with true case here. |
| if (!context()->IsTest()) { |
| __ bind(&done); |