OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
694 const Runtime::Function* function = node->function(); | 694 const Runtime::Function* function = node->function(); |
695 ASSERT(function != NULL); | 695 ASSERT(function != NULL); |
696 ASSERT(function->intrinsic_type == Runtime::INLINE); | 696 ASSERT(function->intrinsic_type == Runtime::INLINE); |
697 InlineFunctionGenerator generator = | 697 InlineFunctionGenerator generator = |
698 FindInlineFunctionGenerator(function->function_id); | 698 FindInlineFunctionGenerator(function->function_id); |
699 ((*this).*(generator))(args); | 699 ((*this).*(generator))(args); |
700 } | 700 } |
701 | 701 |
702 | 702 |
703 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 703 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
704 Comment cmnt(masm_, "[ BinaryOperation"); | 704 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.
| |
705 Token::Value op = expr->op(); | 705 switch (expr->op()) { |
706 Expression* left = expr->left(); | 706 case Token::COMMA: return VisitComma(expr); |
707 Expression* right = expr->right(); | 707 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.
| |
708 | 708 case Token::AND: return VisitAndOr(expr, true); |
709 OverwriteMode mode = NO_OVERWRITE; | 709 default: return VisitCommon(expr); |
710 if (left->ResultOverwriteAllowed()) { | |
711 mode = OVERWRITE_LEFT; | |
712 } else if (right->ResultOverwriteAllowed()) { | |
713 mode = OVERWRITE_RIGHT; | |
714 } | |
715 | |
716 switch (op) { | |
717 case Token::COMMA: | |
718 VisitForEffect(left); | |
719 if (context()->IsTest()) ForwardBailoutToChild(expr); | |
720 context()->HandleExpression(right); | |
721 break; | |
722 | |
723 case Token::OR: | |
724 case Token::AND: | |
725 EmitLogicalOperation(expr); | |
726 break; | |
727 | |
728 case Token::ADD: | |
729 case Token::SUB: | |
730 case Token::DIV: | |
731 case Token::MOD: | |
732 case Token::MUL: | |
733 case Token::BIT_OR: | |
734 case Token::BIT_AND: | |
735 case Token::BIT_XOR: | |
736 case Token::SHL: | |
737 case Token::SHR: | |
738 case Token::SAR: { | |
739 // Load both operands. | |
740 VisitForStackValue(left); | |
741 VisitForAccumulatorValue(right); | |
742 | |
743 SetSourcePosition(expr->position()); | |
744 if (ShouldInlineSmiCase(op)) { | |
745 EmitInlineSmiBinaryOp(expr, op, mode, left, right); | |
746 } else { | |
747 EmitBinaryOp(expr, op, mode); | |
748 } | |
749 break; | |
750 } | |
751 | |
752 default: | |
753 UNREACHABLE(); | |
754 } | 710 } |
755 } | 711 } |
756 | 712 |
757 | 713 |
758 void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { | 714 void FullCodeGenerator::VisitCommon(BinaryOperation* expr) { |
759 Label eval_right, done; | 715 Token::Value op = expr->op(); |
716 Expression* left = expr->left(); | |
717 Expression* right = expr->right(); | |
718 OverwriteMode mode = | |
719 left->ResultOverwriteAllowed() | |
720 ? OVERWRITE_LEFT | |
721 : (right->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE); | |
760 | 722 |
761 context()->EmitLogicalLeft(expr, &eval_right, &done); | 723 VisitForStackValue(left); |
724 VisitForAccumulatorValue(right); | |
762 | 725 |
763 PrepareForBailoutForId(expr->RightId(), NO_REGISTERS); | 726 SetSourcePosition(expr->position()); |
764 __ bind(&eval_right); | 727 if (ShouldInlineSmiCase(op)) { |
728 EmitInlineSmiBinaryOp(expr, op, mode, left, right); | |
729 } else { | |
730 EmitBinaryOp(expr, op, mode); | |
731 } | |
732 } | |
733 | |
734 | |
735 void FullCodeGenerator::VisitComma(BinaryOperation* expr) { | |
736 VisitForEffect(expr->left()); | |
765 if (context()->IsTest()) ForwardBailoutToChild(expr); | 737 if (context()->IsTest()) ForwardBailoutToChild(expr); |
766 context()->HandleExpression(expr->right()); | 738 VisitInSameContext(expr->right()); |
739 } | |
767 | 740 |
741 | |
742 void FullCodeGenerator::VisitAndOr(BinaryOperation* expr, bool is_logical_and) { | |
743 Expression* left = expr->left(); | |
744 Expression* right = expr->right(); | |
745 int rightId = expr->RightId(); | |
Kevin Millikin (Chromium)
2011/05/31 11:46:28
right_id
Sven Panne
2011/05/31 14:30:33
Done.
| |
746 Label done; | |
747 | |
748 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
| |
749 Label eval_right; | |
750 const TestContext* test = TestContext::cast(context()); | |
751 if (is_logical_and) { | |
752 VisitForControl(left, &eval_right, test->false_label(), &eval_right); | |
753 } else { | |
754 VisitForControl(left, test->true_label(), &eval_right, &eval_right); | |
755 } | |
756 PrepareForBailoutForId(rightId, NO_REGISTERS); | |
757 __ bind(&eval_right); | |
758 ForwardBailoutToChild(expr); | |
759 | |
760 } else if (context()->IsAccumulatorValue()) { | |
761 VisitForAccumulatorValue(left); | |
762 // We want the value in the accumulator for the test, and on the stack in | |
763 // case we need it. | |
764 __ push(result_register()); | |
765 Label discard, restore; | |
766 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | |
767 if (is_logical_and) { | |
768 DoTest(&discard, &restore, &restore); | |
769 } else { | |
770 DoTest(&restore, &discard, &restore); | |
771 } | |
772 __ bind(&restore); | |
773 __ pop(result_register()); | |
774 __ jmp(&done); | |
775 __ bind(&discard); | |
776 __ Drop(1); | |
777 PrepareForBailoutForId(rightId, NO_REGISTERS); | |
778 | |
779 } else if (context()->IsStackValue()) { | |
780 VisitForAccumulatorValue(left); | |
781 // We want the value in the accumulator for the test, and on the stack in | |
782 // case we need it. | |
783 __ push(result_register()); | |
784 Label discard; | |
785 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | |
786 if (is_logical_and) { | |
787 DoTest(&discard, &done, &discard); | |
788 } else { | |
789 DoTest(&done, &discard, &discard); | |
790 } | |
791 __ bind(&discard); | |
792 __ Drop(1); | |
793 PrepareForBailoutForId(rightId, NO_REGISTERS); | |
794 | |
795 } else { | |
796 ASSERT(context()->IsEffect()); | |
797 Label eval_right; | |
798 if (is_logical_and) { | |
799 VisitForControl(left, &eval_right, &done, &eval_right); | |
800 } else { | |
801 VisitForControl(left, &done, &eval_right, &eval_right); | |
802 } | |
803 PrepareForBailoutForId(rightId, NO_REGISTERS); | |
804 __ bind(&eval_right); | |
805 } | |
806 | |
807 VisitInSameContext(right); | |
768 __ bind(&done); | 808 __ bind(&done); |
769 } | 809 } |
770 | 810 |
771 | 811 |
772 void FullCodeGenerator::EffectContext::EmitLogicalLeft(BinaryOperation* expr, | |
773 Label* eval_right, | |
774 Label* done) const { | |
775 if (expr->op() == Token::OR) { | |
776 codegen()->VisitForControl(expr->left(), done, eval_right, eval_right); | |
777 } else { | |
778 ASSERT(expr->op() == Token::AND); | |
779 codegen()->VisitForControl(expr->left(), eval_right, done, eval_right); | |
780 } | |
781 } | |
782 | |
783 | |
784 void FullCodeGenerator::AccumulatorValueContext::EmitLogicalLeft( | |
785 BinaryOperation* expr, | |
786 Label* eval_right, | |
787 Label* done) const { | |
788 HandleExpression(expr->left()); | |
789 // We want the value in the accumulator for the test, and on the stack in case | |
790 // we need it. | |
791 __ push(result_register()); | |
792 Label discard, restore; | |
793 if (expr->op() == Token::OR) { | |
794 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | |
795 codegen()->DoTest(&restore, &discard, &restore); | |
796 } else { | |
797 ASSERT(expr->op() == Token::AND); | |
798 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | |
799 codegen()->DoTest(&discard, &restore, &restore); | |
800 } | |
801 __ bind(&restore); | |
802 __ pop(result_register()); | |
803 __ jmp(done); | |
804 __ bind(&discard); | |
805 __ Drop(1); | |
806 } | |
807 | |
808 | |
809 void FullCodeGenerator::StackValueContext::EmitLogicalLeft( | |
810 BinaryOperation* expr, | |
811 Label* eval_right, | |
812 Label* done) const { | |
813 codegen()->VisitForAccumulatorValue(expr->left()); | |
814 // We want the value in the accumulator for the test, and on the stack in case | |
815 // we need it. | |
816 __ push(result_register()); | |
817 Label discard; | |
818 if (expr->op() == Token::OR) { | |
819 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | |
820 codegen()->DoTest(done, &discard, &discard); | |
821 } else { | |
822 ASSERT(expr->op() == Token::AND); | |
823 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); | |
824 codegen()->DoTest(&discard, done, &discard); | |
825 } | |
826 __ bind(&discard); | |
827 __ Drop(1); | |
828 } | |
829 | |
830 | |
831 void FullCodeGenerator::TestContext::EmitLogicalLeft(BinaryOperation* expr, | |
832 Label* eval_right, | |
833 Label* done) const { | |
834 if (expr->op() == Token::OR) { | |
835 codegen()->VisitForControl(expr->left(), | |
836 true_label_, eval_right, eval_right); | |
837 } else { | |
838 ASSERT(expr->op() == Token::AND); | |
839 codegen()->VisitForControl(expr->left(), | |
840 eval_right, false_label_, eval_right); | |
841 } | |
842 } | |
843 | |
844 | |
845 void FullCodeGenerator::ForwardBailoutToChild(Expression* expr) { | 812 void FullCodeGenerator::ForwardBailoutToChild(Expression* expr) { |
846 if (!info_->HasDeoptimizationSupport()) return; | 813 if (!info_->HasDeoptimizationSupport()) return; |
847 ASSERT(context()->IsTest()); | 814 ASSERT(context()->IsTest()); |
848 ASSERT(expr == forward_bailout_stack_->expr()); | 815 ASSERT(expr == forward_bailout_stack_->expr()); |
849 forward_bailout_pending_ = forward_bailout_stack_; | 816 forward_bailout_pending_ = forward_bailout_stack_; |
850 } | 817 } |
851 | 818 |
852 | 819 |
853 void FullCodeGenerator::EffectContext::HandleExpression( | 820 void FullCodeGenerator::VisitInSameContext(Expression* expr) { |
854 Expression* expr) const { | 821 if (context()->IsTest()) { |
855 codegen()->HandleInNonTestContext(expr, NO_REGISTERS); | 822 ForwardBailoutStack stack(expr, forward_bailout_pending_); |
856 } | 823 ForwardBailoutStack* saved = forward_bailout_stack_; |
857 | 824 forward_bailout_pending_ = NULL; |
858 | 825 forward_bailout_stack_ = &stack; |
859 void FullCodeGenerator::AccumulatorValueContext::HandleExpression( | 826 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.
| |
860 Expression* expr) const { | 827 forward_bailout_stack_ = saved; |
861 codegen()->HandleInNonTestContext(expr, TOS_REG); | 828 } else { |
862 } | 829 ASSERT(forward_bailout_pending_ == NULL); |
863 | 830 Visit(expr); |
864 | 831 State state = context()->IsAccumulatorValue() ? TOS_REG : NO_REGISTERS; |
865 void FullCodeGenerator::StackValueContext::HandleExpression( | 832 PrepareForBailout(expr, state); |
866 Expression* expr) const { | 833 // Forwarding bailouts to children is a one shot operation. It should have |
867 codegen()->HandleInNonTestContext(expr, NO_REGISTERS); | 834 // been processed at this point. |
868 } | 835 ASSERT(forward_bailout_pending_ == NULL); |
869 | 836 } |
870 | |
871 void FullCodeGenerator::TestContext::HandleExpression(Expression* expr) const { | |
872 codegen()->VisitInTestContext(expr); | |
873 } | |
874 | |
875 | |
876 void FullCodeGenerator::HandleInNonTestContext(Expression* expr, State state) { | |
877 ASSERT(forward_bailout_pending_ == NULL); | |
878 AstVisitor::Visit(expr); | |
879 PrepareForBailout(expr, state); | |
880 // Forwarding bailouts to children is a one shot operation. It | |
881 // should have been processed at this point. | |
882 ASSERT(forward_bailout_pending_ == NULL); | |
883 } | |
884 | |
885 | |
886 void FullCodeGenerator::VisitInTestContext(Expression* expr) { | |
887 ForwardBailoutStack stack(expr, forward_bailout_pending_); | |
888 ForwardBailoutStack* saved = forward_bailout_stack_; | |
889 forward_bailout_pending_ = NULL; | |
890 forward_bailout_stack_ = &stack; | |
891 AstVisitor::Visit(expr); | |
892 forward_bailout_stack_ = saved; | |
893 } | 837 } |
894 | 838 |
895 | 839 |
896 void FullCodeGenerator::VisitBlock(Block* stmt) { | 840 void FullCodeGenerator::VisitBlock(Block* stmt) { |
897 Comment cmnt(masm_, "[ Block"); | 841 Comment cmnt(masm_, "[ Block"); |
898 Breakable nested_statement(this, stmt); | 842 Breakable nested_statement(this, stmt); |
899 SetStatementPosition(stmt); | 843 SetStatementPosition(stmt); |
900 | 844 |
901 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 845 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
902 VisitStatements(stmt->statements()); | 846 VisitStatements(stmt->statements()); |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1280 __ bind(&true_case); | 1224 __ bind(&true_case); |
1281 SetExpressionPosition(expr->then_expression(), | 1225 SetExpressionPosition(expr->then_expression(), |
1282 expr->then_expression_position()); | 1226 expr->then_expression_position()); |
1283 if (context()->IsTest()) { | 1227 if (context()->IsTest()) { |
1284 const TestContext* for_test = TestContext::cast(context()); | 1228 const TestContext* for_test = TestContext::cast(context()); |
1285 VisitForControl(expr->then_expression(), | 1229 VisitForControl(expr->then_expression(), |
1286 for_test->true_label(), | 1230 for_test->true_label(), |
1287 for_test->false_label(), | 1231 for_test->false_label(), |
1288 NULL); | 1232 NULL); |
1289 } else { | 1233 } else { |
1290 context()->HandleExpression(expr->then_expression()); | 1234 VisitInSameContext(expr->then_expression()); |
1291 __ jmp(&done); | 1235 __ jmp(&done); |
1292 } | 1236 } |
1293 | 1237 |
1294 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS); | 1238 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS); |
1295 __ bind(&false_case); | 1239 __ bind(&false_case); |
1296 if (context()->IsTest()) ForwardBailoutToChild(expr); | 1240 if (context()->IsTest()) ForwardBailoutToChild(expr); |
1297 SetExpressionPosition(expr->else_expression(), | 1241 SetExpressionPosition(expr->else_expression(), |
1298 expr->else_expression_position()); | 1242 expr->else_expression_position()); |
1299 context()->HandleExpression(expr->else_expression()); | 1243 VisitInSameContext(expr->else_expression()); |
1300 // If control flow falls through Visit, merge it with true case here. | 1244 // If control flow falls through Visit, merge it with true case here. |
1301 if (!context()->IsTest()) { | 1245 if (!context()->IsTest()) { |
1302 __ bind(&done); | 1246 __ bind(&done); |
1303 } | 1247 } |
1304 } | 1248 } |
1305 | 1249 |
1306 | 1250 |
1307 void FullCodeGenerator::VisitLiteral(Literal* expr) { | 1251 void FullCodeGenerator::VisitLiteral(Literal* expr) { |
1308 Comment cmnt(masm_, "[ Literal"); | 1252 Comment cmnt(masm_, "[ Literal"); |
1309 context()->Plug(expr->handle()); | 1253 context()->Plug(expr->handle()); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1365 __ Drop(stack_depth); | 1309 __ Drop(stack_depth); |
1366 __ PopTryHandler(); | 1310 __ PopTryHandler(); |
1367 return 0; | 1311 return 0; |
1368 } | 1312 } |
1369 | 1313 |
1370 | 1314 |
1371 #undef __ | 1315 #undef __ |
1372 | 1316 |
1373 | 1317 |
1374 } } // namespace v8::internal | 1318 } } // namespace v8::internal |
OLD | NEW |