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

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

Issue 1524893003: [Interpreter] Add support for break statements in labelled blocks. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@oth-0009-phi
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
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/control-flow-builders.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 ControlScope* outer() const { return outer_; } 97 ControlScope* outer() const { return outer_; }
98 98
99 private: 99 private:
100 BytecodeGenerator* generator_; 100 BytecodeGenerator* generator_;
101 ControlScope* outer_; 101 ControlScope* outer_;
102 102
103 DISALLOW_COPY_AND_ASSIGN(ControlScope); 103 DISALLOW_COPY_AND_ASSIGN(ControlScope);
104 }; 104 };
105 105
106 106
107 // Scoped class for enabling break inside blocks and switch blocks.
108 class BytecodeGenerator::ControlScopeForBreakable final
109 : public BytecodeGenerator::ControlScope {
110 public:
111 ControlScopeForBreakable(BytecodeGenerator* generator,
112 BreakableStatement* statement,
113 BreakableControlFlowBuilder* control_builder)
114 : ControlScope(generator),
115 statement_(statement),
116 control_builder_(control_builder) {}
117
118 protected:
119 virtual bool Execute(Command command, Statement* statement) {
120 if (statement != statement_) return false;
121 switch (command) {
122 case CMD_BREAK:
123 control_builder_->Break();
124 return true;
125 case CMD_CONTINUE:
126 break;
127 }
128 return false;
129 }
130
131 private:
132 Statement* statement_;
133 BreakableControlFlowBuilder* control_builder_;
134 };
135
136
107 // Scoped class for enabling 'break' and 'continue' in iteration 137 // Scoped class for enabling 'break' and 'continue' in iteration
108 // constructs, e.g. do...while, while..., for... 138 // constructs, e.g. do...while, while..., for...
109 class BytecodeGenerator::ControlScopeForIteration 139 class BytecodeGenerator::ControlScopeForIteration final
110 : public BytecodeGenerator::ControlScope { 140 : public BytecodeGenerator::ControlScope {
111 public: 141 public:
112 ControlScopeForIteration(BytecodeGenerator* generator, 142 ControlScopeForIteration(BytecodeGenerator* generator,
113 IterationStatement* statement, 143 IterationStatement* statement,
114 LoopBuilder* loop_builder) 144 LoopBuilder* loop_builder)
115 : ControlScope(generator), 145 : ControlScope(generator),
116 statement_(statement), 146 statement_(statement),
117 loop_builder_(loop_builder) {} 147 loop_builder_(loop_builder) {}
118 148
119 protected: 149 protected:
120 virtual bool Execute(Command command, Statement* statement) { 150 virtual bool Execute(Command command, Statement* statement) {
121 if (statement != statement_) return false; 151 if (statement != statement_) return false;
122 switch (command) { 152 switch (command) {
123 case CMD_BREAK: 153 case CMD_BREAK:
124 loop_builder_->Break(); 154 loop_builder_->Break();
125 return true; 155 return true;
126 case CMD_CONTINUE: 156 case CMD_CONTINUE:
127 loop_builder_->Continue(); 157 loop_builder_->Continue();
128 return true; 158 return true;
129 } 159 }
130 return false; 160 return false;
131 } 161 }
132 162
133 private: 163 private:
134 Statement* statement_; 164 Statement* statement_;
135 LoopBuilder* loop_builder_; 165 LoopBuilder* loop_builder_;
136 }; 166 };
137 167
138 168
139 // Scoped class for enabling 'break' in switch statements.
140 class BytecodeGenerator::ControlScopeForSwitch
141 : public BytecodeGenerator::ControlScope {
142 public:
143 ControlScopeForSwitch(BytecodeGenerator* generator,
144 SwitchStatement* statement,
145 SwitchBuilder* switch_builder)
146 : ControlScope(generator),
147 statement_(statement),
148 switch_builder_(switch_builder) {}
149
150 protected:
151 virtual bool Execute(Command command, Statement* statement) {
152 if (statement != statement_) return false;
153 switch (command) {
154 case CMD_BREAK:
155 switch_builder_->Break();
156 return true;
157 case CMD_CONTINUE:
158 break;
159 }
160 return false;
161 }
162
163 private:
164 Statement* statement_;
165 SwitchBuilder* switch_builder_;
166 };
167
168
169 void BytecodeGenerator::ControlScope::PerformCommand(Command command, 169 void BytecodeGenerator::ControlScope::PerformCommand(Command command,
170 Statement* statement) { 170 Statement* statement) {
171 ControlScope* current = this; 171 ControlScope* current = this;
172 do { 172 do {
173 if (current->Execute(command, statement)) return; 173 if (current->Execute(command, statement)) return;
174 current = current->outer(); 174 current = current->outer();
175 } while (current != nullptr); 175 } while (current != nullptr);
176 UNREACHABLE(); 176 UNREACHABLE();
177 } 177 }
178 178
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 477
478 // Visit declarations within the function scope. 478 // Visit declarations within the function scope.
479 VisitDeclarations(scope()->declarations()); 479 VisitDeclarations(scope()->declarations());
480 480
481 // Visit statements in the function body. 481 // Visit statements in the function body.
482 VisitStatements(info()->literal()->body()); 482 VisitStatements(info()->literal()->body());
483 } 483 }
484 484
485 485
486 void BytecodeGenerator::VisitBlock(Block* stmt) { 486 void BytecodeGenerator::VisitBlock(Block* stmt) {
487 BlockBuilder block_builder(this->builder());
488 ControlScopeForBreakable execution_control(this, stmt, &block_builder);
489
487 if (stmt->scope() == NULL) { 490 if (stmt->scope() == NULL) {
488 // Visit statements in the same scope, no declarations. 491 // Visit statements in the same scope, no declarations.
489 VisitStatements(stmt->statements()); 492 VisitStatements(stmt->statements());
490 } else { 493 } else {
491 // Visit declarations and statements in a block scope. 494 // Visit declarations and statements in a block scope.
492 if (stmt->scope()->NeedsContext()) { 495 if (stmt->scope()->NeedsContext()) {
493 VisitNewLocalBlockContext(stmt->scope()); 496 VisitNewLocalBlockContext(stmt->scope());
494 ContextScope scope(this, stmt->scope()); 497 ContextScope scope(this, stmt->scope());
495 VisitDeclarations(stmt->scope()->declarations()); 498 VisitDeclarations(stmt->scope()->declarations());
496 VisitStatements(stmt->statements()); 499 VisitStatements(stmt->statements());
497 } else { 500 } else {
498 VisitDeclarations(stmt->scope()->declarations()); 501 VisitDeclarations(stmt->scope()->declarations());
499 VisitStatements(stmt->statements()); 502 VisitStatements(stmt->statements());
500 } 503 }
501 } 504 }
505 if (stmt->labels() != nullptr) block_builder.EndBlock();
502 } 506 }
503 507
504 508
505 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { 509 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
506 Variable* variable = decl->proxy()->var(); 510 Variable* variable = decl->proxy()->var();
507 VariableMode mode = decl->mode(); 511 VariableMode mode = decl->mode();
508 // Const and let variables are initialized with the hole so that we can 512 // Const and let variables are initialized with the hole so that we can
509 // check that they are only assigned once. 513 // check that they are only assigned once.
510 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; 514 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
511 switch (variable->location()) { 515 switch (variable->location()) {
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 682
679 683
680 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 684 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
681 UNIMPLEMENTED(); 685 UNIMPLEMENTED();
682 } 686 }
683 687
684 688
685 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 689 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
686 ZoneList<CaseClause*>* clauses = stmt->cases(); 690 ZoneList<CaseClause*>* clauses = stmt->cases();
687 SwitchBuilder switch_builder(builder(), clauses->length()); 691 SwitchBuilder switch_builder(builder(), clauses->length());
688 ControlScopeForSwitch scope(this, stmt, &switch_builder); 692 ControlScopeForBreakable scope(this, stmt, &switch_builder);
689 int default_index = -1; 693 int default_index = -1;
690 694
691 // Keep the switch value in a register until a case matches. 695 // Keep the switch value in a register until a case matches.
692 Register tag = VisitForRegisterValue(stmt->tag()); 696 Register tag = VisitForRegisterValue(stmt->tag());
693 697
694 // Iterate over all cases and create nodes for label comparison. 698 // Iterate over all cases and create nodes for label comparison.
695 BytecodeLabel done_label; 699 BytecodeLabel done_label;
696 for (int i = 0; i < clauses->length(); i++) { 700 for (int i = 0; i < clauses->length(); i++) {
697 CaseClause* clause = clauses->at(i); 701 CaseClause* clause = clauses->at(i);
698 702
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 } else if (stmt->cond()->ToBooleanIsTrue()) { 750 } else if (stmt->cond()->ToBooleanIsTrue()) {
747 loop_builder.Condition(); 751 loop_builder.Condition();
748 Visit(stmt->body()); 752 Visit(stmt->body());
749 loop_builder.JumpToHeader(); 753 loop_builder.JumpToHeader();
750 } else { 754 } else {
751 Visit(stmt->body()); 755 Visit(stmt->body());
752 loop_builder.Condition(); 756 loop_builder.Condition();
753 VisitForAccumulatorValue(stmt->cond()); 757 VisitForAccumulatorValue(stmt->cond());
754 loop_builder.JumpToHeaderIfTrue(); 758 loop_builder.JumpToHeaderIfTrue();
755 } 759 }
756 loop_builder.LoopEnd(); 760 loop_builder.EndLoop();
757 } 761 }
758 762
759 763
760 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 764 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
761 if (stmt->cond()->ToBooleanIsFalse()) { 765 if (stmt->cond()->ToBooleanIsFalse()) {
762 // If the condition is false there is no need to generate the loop. 766 // If the condition is false there is no need to generate the loop.
763 return; 767 return;
764 } 768 }
765 769
766 LoopBuilder loop_builder(builder()); 770 LoopBuilder loop_builder(builder());
767 ControlScopeForIteration execution_control(this, stmt, &loop_builder); 771 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
768 loop_builder.LoopHeader(); 772 loop_builder.LoopHeader();
769 loop_builder.Condition(); 773 loop_builder.Condition();
770 if (!stmt->cond()->ToBooleanIsTrue()) { 774 if (!stmt->cond()->ToBooleanIsTrue()) {
771 VisitForAccumulatorValue(stmt->cond()); 775 VisitForAccumulatorValue(stmt->cond());
772 loop_builder.BreakIfFalse(); 776 loop_builder.BreakIfFalse();
773 } 777 }
774 Visit(stmt->body()); 778 Visit(stmt->body());
775 loop_builder.JumpToHeader(); 779 loop_builder.JumpToHeader();
776 loop_builder.LoopEnd(); 780 loop_builder.EndLoop();
777 } 781 }
778 782
779 783
780 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 784 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
781 if (stmt->init() != nullptr) { 785 if (stmt->init() != nullptr) {
782 Visit(stmt->init()); 786 Visit(stmt->init());
783 } 787 }
784 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { 788 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
785 // If the condition is known to be false there is no need to generate 789 // If the condition is known to be false there is no need to generate
786 // body, next or condition blocks. Init block should be generated. 790 // body, next or condition blocks. Init block should be generated.
787 return; 791 return;
788 } 792 }
789 793
790 LoopBuilder loop_builder(builder()); 794 LoopBuilder loop_builder(builder());
791 ControlScopeForIteration execution_control(this, stmt, &loop_builder); 795 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
792 796
793 loop_builder.LoopHeader(); 797 loop_builder.LoopHeader();
794 loop_builder.Condition(); 798 loop_builder.Condition();
795 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { 799 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
796 VisitForAccumulatorValue(stmt->cond()); 800 VisitForAccumulatorValue(stmt->cond());
797 loop_builder.BreakIfFalse(); 801 loop_builder.BreakIfFalse();
798 } 802 }
799 Visit(stmt->body()); 803 Visit(stmt->body());
800 if (stmt->next() != nullptr) { 804 if (stmt->next() != nullptr) {
801 loop_builder.Next(); 805 loop_builder.Next();
802 Visit(stmt->next()); 806 Visit(stmt->next());
803 } 807 }
804 loop_builder.JumpToHeader(); 808 loop_builder.JumpToHeader();
805 loop_builder.LoopEnd(); 809 loop_builder.EndLoop();
806 } 810 }
807 811
808 812
809 void BytecodeGenerator::VisitForInAssignment(Expression* expr, 813 void BytecodeGenerator::VisitForInAssignment(Expression* expr,
810 FeedbackVectorSlot slot) { 814 FeedbackVectorSlot slot) {
811 DCHECK(expr->IsValidReferenceExpression()); 815 DCHECK(expr->IsValidReferenceExpression());
812 816
813 // Evaluate assignment starting with the value to be stored in the 817 // Evaluate assignment starting with the value to be stored in the
814 // accumulator. 818 // accumulator.
815 Property* property = expr->AsProperty(); 819 Property* property = expr->AsProperty();
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
887 loop_builder.ContinueIfUndefined(); 891 loop_builder.ContinueIfUndefined();
888 892
889 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); 893 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
890 Visit(stmt->body()); 894 Visit(stmt->body());
891 895
892 // TODO(oth): replace CountOperation here with ForInStep. 896 // TODO(oth): replace CountOperation here with ForInStep.
893 loop_builder.Next(); 897 loop_builder.Next();
894 builder()->LoadAccumulatorWithRegister(index).CountOperation( 898 builder()->LoadAccumulatorWithRegister(index).CountOperation(
895 Token::Value::ADD, language_mode_strength()); 899 Token::Value::ADD, language_mode_strength());
896 loop_builder.JumpToHeader(); 900 loop_builder.JumpToHeader();
897 loop_builder.LoopEnd(); 901 loop_builder.EndLoop();
898 } 902 }
899 903
900 904
901 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { 905 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
902 UNIMPLEMENTED(); 906 UNIMPLEMENTED();
903 } 907 }
904 908
905 909
906 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { 910 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
907 if (FLAG_ignition_fake_try_catch) { 911 if (FLAG_ignition_fake_try_catch) {
(...skipping 1290 matching lines...) Expand 10 before | Expand all | Expand 10 after
2198 } 2202 }
2199 2203
2200 2204
2201 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2205 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2202 return info()->feedback_vector()->GetIndex(slot); 2206 return info()->feedback_vector()->GetIndex(slot);
2203 } 2207 }
2204 2208
2205 } // namespace interpreter 2209 } // namespace interpreter
2206 } // namespace internal 2210 } // namespace internal
2207 } // namespace v8 2211 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/control-flow-builders.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698