Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(689)

Side by Side Diff: src/full-codegen.cc

Issue 6976028: Reduced the code ping-pong between the full code generator and contexts a bit. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW
« src/full-codegen.h ('K') | « src/full-codegen.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698