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 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' in switch statements. | |
108 class BytecodeGenerator::ControlScopeForSwitch | |
oth
2015/10/30 10:10:04
Nit - suggest putting ControlScopeForSwitch after
rmcilroy
2015/10/30 11:46:59
Done.
| |
109 : public BytecodeGenerator::ControlScope { | |
110 public: | |
111 ControlScopeForSwitch(BytecodeGenerator* generator, | |
112 SwitchStatement* statement, | |
113 SwitchBuilder* switch_builder) | |
114 : ControlScope(generator), | |
115 statement_(statement), | |
116 switch_builder_(switch_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 switch_builder_->Break(); | |
124 return true; | |
125 case CMD_CONTINUE: | |
126 break; | |
127 } | |
128 return false; | |
129 } | |
130 | |
131 private: | |
132 Statement* statement_; | |
133 SwitchBuilder* switch_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 |
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), |
(...skipping 415 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 |