| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |