| Index: src/interpreter/bytecode-generator.cc
 | 
| diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
 | 
| index 8e6c9c53295a530ed45649645f7dc1f0a7953282..3eb010510da19f6ed3571002885791c878bb6f63 100644
 | 
| --- a/src/interpreter/bytecode-generator.cc
 | 
| +++ b/src/interpreter/bytecode-generator.cc
 | 
| @@ -136,6 +136,36 @@ class BytecodeGenerator::ControlScopeForIteration
 | 
|  };
 | 
|  
 | 
|  
 | 
| +// Scoped class for enabling 'break' in switch statements.
 | 
| +class BytecodeGenerator::ControlScopeForSwitch
 | 
| +    : 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_;
 | 
| +};
 | 
| +
 | 
| +
 | 
|  void BytecodeGenerator::ControlScope::PerformCommand(Command command,
 | 
|                                                       Statement* statement) {
 | 
|    ControlScope* current = this;
 | 
| @@ -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) {
 | 
| 
 |