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

Unified Diff: src/interpreter/bytecode-generator.cc

Issue 1415093006: [Interpreter] Add switch support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@int_wideidx
Patch Set: Created 5 years, 2 months 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 side-by-side diff with in-line comments
Download patch
Index: src/interpreter/bytecode-generator.cc
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
index 8e6c9c53295a530ed45649645f7dc1f0a7953282..50dd3f5936038d954fa4dffc0c596e618e7757a4 100644
--- a/src/interpreter/bytecode-generator.cc
+++ b/src/interpreter/bytecode-generator.cc
@@ -104,6 +104,36 @@ class BytecodeGenerator::ControlScope BASE_EMBEDDED {
};
+// Scoped class for enabling 'break' in switch statements.
+class BytecodeGenerator::ControlScopeForSwitch
oth 2015/10/30 10:10:04 Nit - suggest putting ControlScopeForSwitch after
rmcilroy 2015/10/30 11:46:59 Done.
+ : public BytecodeGenerator::ControlScope {
+ public:
+ ControlScopeForSwitch(BytecodeGenerator* generator,
+ SwitchStatement* statement,
+ SwitchBuilder* switch_builder)
+ : ControlScope(generator),
+ statement_(statement),
+ switch_builder_(switch_builder) {}
+
+ protected:
+ virtual bool Execute(Command command, Statement* statement) {
+ if (statement != statement_) return false;
+ switch (command) {
+ case CMD_BREAK:
+ switch_builder_->Break();
+ return true;
+ case CMD_CONTINUE:
+ break;
+ }
+ return false;
+ }
+
+ private:
+ Statement* statement_;
+ SwitchBuilder* switch_builder_;
+};
+
+
// Scoped class for enabling 'break' and 'continue' in iteration
// constructs, e.g. do...while, while..., for...
class BytecodeGenerator::ControlScopeForIteration
@@ -539,11 +569,57 @@ void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
- UNIMPLEMENTED();
+ ZoneList<CaseClause*>* clauses = stmt->cases();
+ SwitchBuilder switch_builder(builder(), clauses->length());
+ ControlScopeForSwitch scope(this, stmt, &switch_builder);
+ int default_index = -1;
+
+ // Keep the switch value in a register until a case matches.
+ Register tag = VisitForRegisterValue(stmt->tag());
+
+ // Iterate over all cases and create nodes for label comparison.
+ BytecodeLabel done_label;
+ for (int i = 0; i < clauses->length(); i++) {
+ CaseClause* clause = clauses->at(i);
+
+ // The default is not a test, remember index.
+ if (clause->is_default()) {
+ default_index = i;
+ continue;
+ }
+
+ // Perform label comparison as if via '===' with tag.
+ VisitForAccumulatorValue(clause->label());
+ builder()->CompareOperation(Token::Value::EQ_STRICT, tag,
+ language_mode_strength());
+ switch_builder.Case(i);
+ }
+
+ if (default_index >= 0) {
+ // Emit default jump if there is a default case.
+ switch_builder.DefaultAt(default_index);
+ } else {
+ // Otherwise if we have reached here none of the cases matched, so jump to
+ // done.
+ builder()->Jump(&done_label);
+ }
+
+ // Iterate over all cases and create the case bodies.
+ for (int i = 0; i < clauses->length(); i++) {
+ CaseClause* clause = clauses->at(i);
+ switch_builder.SetCaseTarget(i);
+ VisitStatements(clause->statements());
+ }
+ builder()->Bind(&done_label);
+
+ switch_builder.SetBreakTarget(done_label);
}
-void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
+ // Handled entirely in VisitSwitchStatement.
+ UNREACHABLE();
+}
void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {

Powered by Google App Engine
This is Rietveld 408576698