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/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/interpreter/control-flow-builders.h" | 8 #include "src/interpreter/control-flow-builders.h" |
9 #include "src/objects.h" | 9 #include "src/objects.h" |
10 #include "src/parser.h" | 10 #include "src/parser.h" |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 } | 129 } |
130 return false; | 130 return false; |
131 } | 131 } |
132 | 132 |
133 private: | 133 private: |
134 Statement* statement_; | 134 Statement* statement_; |
135 LoopBuilder* loop_builder_; | 135 LoopBuilder* loop_builder_; |
136 }; | 136 }; |
137 | 137 |
138 | 138 |
| 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 |
139 void BytecodeGenerator::ControlScope::PerformCommand(Command command, | 169 void BytecodeGenerator::ControlScope::PerformCommand(Command command, |
140 Statement* statement) { | 170 Statement* statement) { |
141 ControlScope* current = this; | 171 ControlScope* current = this; |
142 do { | 172 do { |
143 if (current->Execute(command, statement)) return; | 173 if (current->Execute(command, statement)) return; |
144 current = current->outer(); | 174 current = current->outer(); |
145 } while (current != nullptr); | 175 } while (current != nullptr); |
146 UNREACHABLE(); | 176 UNREACHABLE(); |
147 } | 177 } |
148 | 178 |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 builder()->Return(); | 562 builder()->Return(); |
533 } | 563 } |
534 | 564 |
535 | 565 |
536 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 566 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
537 UNIMPLEMENTED(); | 567 UNIMPLEMENTED(); |
538 } | 568 } |
539 | 569 |
540 | 570 |
541 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 571 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
542 UNIMPLEMENTED(); | 572 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 573 SwitchBuilder switch_builder(builder(), clauses->length()); |
| 574 ControlScopeForSwitch scope(this, stmt, &switch_builder); |
| 575 int default_index = -1; |
| 576 |
| 577 // Keep the switch value in a register until a case matches. |
| 578 Register tag = VisitForRegisterValue(stmt->tag()); |
| 579 |
| 580 // Iterate over all cases and create nodes for label comparison. |
| 581 BytecodeLabel done_label; |
| 582 for (int i = 0; i < clauses->length(); i++) { |
| 583 CaseClause* clause = clauses->at(i); |
| 584 |
| 585 // The default is not a test, remember index. |
| 586 if (clause->is_default()) { |
| 587 default_index = i; |
| 588 continue; |
| 589 } |
| 590 |
| 591 // Perform label comparison as if via '===' with tag. |
| 592 VisitForAccumulatorValue(clause->label()); |
| 593 builder()->CompareOperation(Token::Value::EQ_STRICT, tag, |
| 594 language_mode_strength()); |
| 595 switch_builder.Case(i); |
| 596 } |
| 597 |
| 598 if (default_index >= 0) { |
| 599 // Emit default jump if there is a default case. |
| 600 switch_builder.DefaultAt(default_index); |
| 601 } else { |
| 602 // Otherwise if we have reached here none of the cases matched, so jump to |
| 603 // done. |
| 604 builder()->Jump(&done_label); |
| 605 } |
| 606 |
| 607 // Iterate over all cases and create the case bodies. |
| 608 for (int i = 0; i < clauses->length(); i++) { |
| 609 CaseClause* clause = clauses->at(i); |
| 610 switch_builder.SetCaseTarget(i); |
| 611 VisitStatements(clause->statements()); |
| 612 } |
| 613 builder()->Bind(&done_label); |
| 614 |
| 615 switch_builder.SetBreakTarget(done_label); |
543 } | 616 } |
544 | 617 |
545 | 618 |
546 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } | 619 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { |
| 620 // Handled entirely in VisitSwitchStatement. |
| 621 UNREACHABLE(); |
| 622 } |
547 | 623 |
548 | 624 |
549 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 625 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
550 LoopBuilder loop_builder(builder()); | 626 LoopBuilder loop_builder(builder()); |
551 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 627 ControlScopeForIteration execution_control(this, stmt, &loop_builder); |
552 | 628 |
553 BytecodeLabel body_label, condition_label, done_label; | 629 BytecodeLabel body_label, condition_label, done_label; |
554 builder()->Bind(&body_label); | 630 builder()->Bind(&body_label); |
555 Visit(stmt->body()); | 631 Visit(stmt->body()); |
556 builder()->Bind(&condition_label); | 632 builder()->Bind(&condition_label); |
(...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2055 } | 2131 } |
2056 | 2132 |
2057 | 2133 |
2058 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2134 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2059 return info()->feedback_vector()->GetIndex(slot); | 2135 return info()->feedback_vector()->GetIndex(slot); |
2060 } | 2136 } |
2061 | 2137 |
2062 } // namespace interpreter | 2138 } // namespace interpreter |
2063 } // namespace internal | 2139 } // namespace internal |
2064 } // namespace v8 | 2140 } // namespace v8 |
OLD | NEW |