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

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 1502243002: [Interpreter] Local flow control in the bytecode graph builder. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 5 years 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
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/interpreter/bytecode-generator.h" 5 #include "src/interpreter/bytecode-generator.h"
6 6
7 #include "src/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/compiler.h" 8 #include "src/compiler.h"
9 #include "src/interpreter/control-flow-builders.h" 9 #include "src/interpreter/control-flow-builders.h"
10 #include "src/objects.h" 10 #include "src/objects.h"
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 } 621 }
622 622
623 623
624 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 624 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
625 } 625 }
626 626
627 627
628 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { 628 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
629 BytecodeLabel else_label, end_label; 629 BytecodeLabel else_label, end_label;
630 if (stmt->condition()->ToBooleanIsTrue()) { 630 if (stmt->condition()->ToBooleanIsTrue()) {
631 // Generate only then block. 631 // Generate then block unconditionally as always true.
632 Visit(stmt->then_statement()); 632 Visit(stmt->then_statement());
633 } else if (stmt->condition()->ToBooleanIsFalse()) { 633 } else if (stmt->condition()->ToBooleanIsFalse()) {
634 // Generate only else block if it exists. 634 // Generate else block unconditionally if it exists.
635 if (stmt->HasElseStatement()) { 635 if (stmt->HasElseStatement()) {
636 Visit(stmt->else_statement()); 636 Visit(stmt->else_statement());
637 } 637 }
638 } else { 638 } else {
639 // TODO(oth): If then statement is BreakStatement or
640 // ContinueStatement we can reduce number of generated
641 // jump/jump_ifs here. See BasicLoops test.
639 VisitForAccumulatorValue(stmt->condition()); 642 VisitForAccumulatorValue(stmt->condition());
640 builder()->JumpIfFalse(&else_label); 643 builder()->JumpIfFalse(&else_label);
641 Visit(stmt->then_statement()); 644 Visit(stmt->then_statement());
642 if (stmt->HasElseStatement()) { 645 if (stmt->HasElseStatement()) {
643 builder()->Jump(&end_label); 646 builder()->Jump(&end_label);
644 builder()->Bind(&else_label); 647 builder()->Bind(&else_label);
645 Visit(stmt->else_statement()); 648 Visit(stmt->else_statement());
646 } else { 649 } else {
647 builder()->Bind(&else_label); 650 builder()->Bind(&else_label);
648 } 651 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 732
730 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { 733 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
731 // Handled entirely in VisitSwitchStatement. 734 // Handled entirely in VisitSwitchStatement.
732 UNREACHABLE(); 735 UNREACHABLE();
733 } 736 }
734 737
735 738
736 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 739 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
737 LoopBuilder loop_builder(builder()); 740 LoopBuilder loop_builder(builder());
738 ControlScopeForIteration execution_control(this, stmt, &loop_builder); 741 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
739 BytecodeLabel body_label, condition_label, done_label; 742 loop_builder.LoopHeader();
740 if (stmt->cond()->ToBooleanIsFalse()) { 743 if (stmt->cond()->ToBooleanIsFalse()) {
741 Visit(stmt->body()); 744 Visit(stmt->body());
742 // Bind condition_label and done_label for processing continue and break. 745 loop_builder.Condition();
743 builder()->Bind(&condition_label);
744 builder()->Bind(&done_label);
745 } else { 746 } else {
746 builder()->Bind(&body_label);
747 Visit(stmt->body());
748
749 builder()->Bind(&condition_label);
750 if (stmt->cond()->ToBooleanIsTrue()) { 747 if (stmt->cond()->ToBooleanIsTrue()) {
rmcilroy 2015/12/15 17:35:44 nit - avoid nesting this if, just make it an "else
oth 2015/12/15 22:42:17 Done.
751 builder()->Jump(&body_label); 748 loop_builder.Condition();
749 Visit(stmt->body());
750 loop_builder.JumpToHeader();
752 } else { 751 } else {
752 Visit(stmt->body());
753 loop_builder.Condition();
753 VisitForAccumulatorValue(stmt->cond()); 754 VisitForAccumulatorValue(stmt->cond());
754 builder()->JumpIfTrue(&body_label); 755 loop_builder.JumpToHeaderIfTrue();
rmcilroy 2015/12/15 17:35:44 Any reason this can't be written as: Visit(stmt-
oth 2015/12/15 22:42:17 The Condition() is the target for continue stateme
755 } 756 }
756 builder()->Bind(&done_label);
757 } 757 }
758 loop_builder.SetBreakTarget(done_label); 758 loop_builder.LoopEnd();
759 loop_builder.SetContinueTarget(condition_label);
760 } 759 }
761 760
762 761
763 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 762 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
764 LoopBuilder loop_builder(builder());
765 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
766
767 BytecodeLabel body_label, condition_label, done_label;
768 if (stmt->cond()->ToBooleanIsFalse()) { 763 if (stmt->cond()->ToBooleanIsFalse()) {
769 // If the condition is false there is no need to generate the loop. 764 // If the condition is false there is no need to generate the loop.
770 return; 765 return;
771 } 766 }
772 767
768 LoopBuilder loop_builder(builder());
769 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
770 loop_builder.LoopHeader();
771 loop_builder.Condition();
773 if (!stmt->cond()->ToBooleanIsTrue()) { 772 if (!stmt->cond()->ToBooleanIsTrue()) {
774 builder()->Jump(&condition_label); 773 VisitForAccumulatorValue(stmt->cond());
774 loop_builder.BreakIfFalse();
775 } 775 }
776 builder()->Bind(&body_label);
777 Visit(stmt->body()); 776 Visit(stmt->body());
778 777 loop_builder.JumpToHeader();
779 builder()->Bind(&condition_label); 778 loop_builder.LoopEnd();
780 if (stmt->cond()->ToBooleanIsTrue()) {
781 builder()->Jump(&body_label);
782 } else {
783 VisitForAccumulatorValue(stmt->cond());
784 builder()->JumpIfTrue(&body_label);
785 }
786 builder()->Bind(&done_label);
787
788 loop_builder.SetBreakTarget(done_label);
789 loop_builder.SetContinueTarget(condition_label);
790 } 779 }
791 780
792 781
793 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 782 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
794 LoopBuilder loop_builder(builder());
795 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
796
797 if (stmt->init() != nullptr) { 783 if (stmt->init() != nullptr) {
798 Visit(stmt->init()); 784 Visit(stmt->init());
799 } 785 }
800
801 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { 786 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
802 // If the condition is known to be false there is no need to generate 787 // If the condition is known to be false there is no need to generate
803 // body, next or condition blocks. Init block should be generated. 788 // body, next or condition blocks. Init block should be generated.
804 return; 789 return;
805 } 790 }
806 791
807 BytecodeLabel body_label, condition_label, next_label, done_label; 792 LoopBuilder loop_builder(builder());
793 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
794
795 loop_builder.LoopHeader();
796 loop_builder.Condition();
808 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { 797 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
809 builder()->Jump(&condition_label); 798 VisitForAccumulatorValue(stmt->cond());
799 loop_builder.BreakIfFalse();
810 } 800 }
811 builder()->Bind(&body_label);
812 Visit(stmt->body()); 801 Visit(stmt->body());
813 builder()->Bind(&next_label);
814 if (stmt->next() != nullptr) { 802 if (stmt->next() != nullptr) {
803 loop_builder.Next();
815 Visit(stmt->next()); 804 Visit(stmt->next());
816 } 805 }
817 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { 806 loop_builder.JumpToHeader();
818 builder()->Bind(&condition_label); 807 loop_builder.LoopEnd();
819 VisitForAccumulatorValue(stmt->cond());
820 builder()->JumpIfTrue(&body_label);
821 } else {
822 builder()->Jump(&body_label);
823 }
824 builder()->Bind(&done_label);
825
826 loop_builder.SetBreakTarget(done_label);
827 loop_builder.SetContinueTarget(next_label);
828 } 808 }
829 809
830 810
831 void BytecodeGenerator::VisitForInAssignment(Expression* expr, 811 void BytecodeGenerator::VisitForInAssignment(Expression* expr,
832 FeedbackVectorSlot slot) { 812 FeedbackVectorSlot slot) {
833 DCHECK(expr->IsValidReferenceExpression()); 813 DCHECK(expr->IsValidReferenceExpression());
834 814
835 // Evaluate assignment starting with the value to be stored in the 815 // Evaluate assignment starting with the value to be stored in the
836 // accumulator. 816 // accumulator.
837 Property* property = expr->AsProperty(); 817 Property* property = expr->AsProperty();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
891 Register receiver = execution_result()->NewRegister(); 871 Register receiver = execution_result()->NewRegister();
892 builder()->CastAccumulatorToJSObject(); 872 builder()->CastAccumulatorToJSObject();
893 builder()->StoreAccumulatorInRegister(receiver); 873 builder()->StoreAccumulatorInRegister(receiver);
894 builder()->CallRuntime(Runtime::kGetPropertyNamesFast, receiver, 1); 874 builder()->CallRuntime(Runtime::kGetPropertyNamesFast, receiver, 1);
895 builder()->ForInPrepare(receiver); 875 builder()->ForInPrepare(receiver);
896 loop_builder.BreakIfUndefined(); 876 loop_builder.BreakIfUndefined();
897 877
898 Register for_in_state = execution_result()->NewRegister(); 878 Register for_in_state = execution_result()->NewRegister();
899 builder()->StoreAccumulatorInRegister(for_in_state); 879 builder()->StoreAccumulatorInRegister(for_in_state);
900 880
901 // The loop. 881 // Check loop termination (accumulator holds index).
902 BytecodeLabel condition_label, break_label, continue_label;
903 Register index = receiver; // Re-using register as receiver no longer used. 882 Register index = receiver; // Re-using register as receiver no longer used.
904 builder()->LoadLiteral(Smi::FromInt(0)); 883 builder()->LoadLiteral(Smi::FromInt(0));
905 884 loop_builder.LoopHeader();
906 // Check loop termination (accumulator holds index). 885 loop_builder.Condition();
907 builder() 886 builder()->StoreAccumulatorInRegister(index).ForInDone(for_in_state);
908 ->Bind(&condition_label)
909 .StoreAccumulatorInRegister(index)
910 .ForInDone(for_in_state);
911 loop_builder.BreakIfTrue(); 887 loop_builder.BreakIfTrue();
912
913 // Get the next item.
914 builder()->ForInNext(for_in_state, index); 888 builder()->ForInNext(for_in_state, index);
915
916 // Start again if the item, currently in the accumulator, is undefined.
917 loop_builder.ContinueIfUndefined(); 889 loop_builder.ContinueIfUndefined();
918 890
919 // Store the value in the each variable.
920 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); 891 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
921 // NB the user's loop variable will be assigned the value of each so
922 // even an empty body will have this assignment.
923 Visit(stmt->body()); 892 Visit(stmt->body());
924 893
925 // Increment the index and start loop again. 894 // TODO(oth): replace CountOperation here with ForInStep.
926 builder() 895 loop_builder.Next();
927 ->Bind(&continue_label) 896 builder()->LoadAccumulatorWithRegister(index).CountOperation(
928 .LoadAccumulatorWithRegister(index) 897 Token::Value::ADD, language_mode_strength());
929 .CountOperation(Token::Value::ADD, language_mode_strength()) 898 loop_builder.JumpToHeader();
930 .Jump(&condition_label); 899 loop_builder.LoopEnd();
931
932 // End of the loop.
933 builder()->Bind(&break_label);
934
935 loop_builder.SetBreakTarget(break_label);
936 loop_builder.SetContinueTarget(continue_label);
937 } 900 }
938 901
939 902
940 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { 903 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
941 UNIMPLEMENTED(); 904 UNIMPLEMENTED();
942 } 905 }
943 906
944 907
945 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { 908 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
946 if (FLAG_ignition_fake_try_catch) { 909 if (FLAG_ignition_fake_try_catch) {
(...skipping 1290 matching lines...) Expand 10 before | Expand all | Expand 10 after
2237 } 2200 }
2238 2201
2239 2202
2240 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2203 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2241 return info()->feedback_vector()->GetIndex(slot); 2204 return info()->feedback_vector()->GetIndex(slot);
2242 } 2205 }
2243 2206
2244 } // namespace interpreter 2207 } // namespace interpreter
2245 } // namespace internal 2208 } // namespace internal
2246 } // namespace v8 2209 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698