| Index: src/hydrogen.cc
 | 
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
 | 
| index 8dbecac1191d49440fd755860a559cd71b75e2a5..96de7922d8753b9b6c121a1372cc99804c4c9f0d 100644
 | 
| --- a/src/hydrogen.cc
 | 
| +++ b/src/hydrogen.cc
 | 
| @@ -4141,31 +4141,31 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
 | 
|    const int kCaseClauseLimit = 128;
 | 
|    ZoneList<CaseClause*>* clauses = stmt->cases();
 | 
|    int clause_count = clauses->length();
 | 
| +  ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
 | 
|    if (clause_count > kCaseClauseLimit) {
 | 
|      return Bailout(kSwitchStatementTooManyClauses);
 | 
|    }
 | 
|  
 | 
|    ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH);
 | 
| -  if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) {
 | 
| -    return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels);
 | 
| -  }
 | 
|  
 | 
|    CHECK_ALIVE(VisitForValue(stmt->tag()));
 | 
|    Add<HSimulate>(stmt->EntryId());
 | 
| -  HValue* tag_value = Pop();
 | 
| -  HBasicBlock* first_test_block = current_block();
 | 
| +  HValue* tag_value = Top();
 | 
|  
 | 
|    HUnaryControlInstruction* string_check = NULL;
 | 
|    HBasicBlock* not_string_block = NULL;
 | 
|  
 | 
|    // Test switch's tag value if all clauses are string literals
 | 
|    if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) {
 | 
| -    first_test_block = graph()->CreateBasicBlock();
 | 
| +    HBasicBlock* first_test_block = graph()->CreateBasicBlock();
 | 
|      not_string_block = graph()->CreateBasicBlock();
 | 
|      string_check = New<HIsStringAndBranch>(
 | 
|          tag_value, first_test_block, not_string_block);
 | 
|      FinishCurrentBlock(string_check);
 | 
|  
 | 
| +    set_current_block(not_string_block);
 | 
| +    Drop(1);  // tag_value
 | 
| +
 | 
|      set_current_block(first_test_block);
 | 
|    }
 | 
|  
 | 
| @@ -4174,7 +4174,8 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
 | 
|    for (int i = 0; i < clause_count; ++i) {
 | 
|      CaseClause* clause = clauses->at(i);
 | 
|      if (clause->is_default()) {
 | 
| -      default_id = clause->EntryId();
 | 
| +      body_blocks.Add(NULL, zone());
 | 
| +      if (default_id.IsNone()) default_id = clause->EntryId();
 | 
|        continue;
 | 
|      }
 | 
|  
 | 
| @@ -4182,9 +4183,6 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
 | 
|      CHECK_ALIVE(VisitForValue(clause->label()));
 | 
|      HValue* label_value = Pop();
 | 
|  
 | 
| -    HBasicBlock* next_test_block = graph()->CreateBasicBlock();
 | 
| -    HBasicBlock* body_block = graph()->CreateBasicBlock();
 | 
| -
 | 
|      HControlInstruction* compare;
 | 
|  
 | 
|      if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
 | 
| @@ -4199,22 +4197,39 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
 | 
|        compare_->set_observed_input_representation(
 | 
|            Representation::Smi(), Representation::Smi());
 | 
|        compare = compare_;
 | 
| -    } else {
 | 
| +    } else if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) {
 | 
|        compare = New<HStringCompareAndBranch>(tag_value,
 | 
|                                               label_value,
 | 
|                                               Token::EQ_STRICT);
 | 
| +    } else {
 | 
| +      HValue* test = Add<HCompareGeneric>(tag_value,
 | 
| +                                          label_value,
 | 
| +                                          Token::EQ_STRICT);
 | 
| +      if (test->HasObservableSideEffects()) {
 | 
| +        Push(test);
 | 
| +        Add<HSimulate>(clause->id(), REMOVABLE_SIMULATE);
 | 
| +        Drop(1);
 | 
| +      }
 | 
| +      compare = New<HBranch>(test);
 | 
|      }
 | 
|  
 | 
| +    HBasicBlock* next_test_block = graph()->CreateBasicBlock();
 | 
| +    HBasicBlock* body_block = graph()->CreateBasicBlock();
 | 
| +    body_blocks.Add(body_block, zone());
 | 
|      compare->SetSuccessorAt(0, body_block);
 | 
|      compare->SetSuccessorAt(1, next_test_block);
 | 
|      FinishCurrentBlock(compare);
 | 
|  
 | 
| +    set_current_block(body_block);
 | 
| +    Drop(1);  // tag_value
 | 
| +
 | 
|      set_current_block(next_test_block);
 | 
|    }
 | 
|  
 | 
|    // Save the current block to use for the default or to join with the
 | 
|    // exit.
 | 
|    HBasicBlock* last_block = current_block();
 | 
| +  Drop(1);  // tag_value
 | 
|  
 | 
|    if (not_string_block != NULL) {
 | 
|      BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId();
 | 
| @@ -4223,7 +4238,6 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
 | 
|  
 | 
|    // 2. Loop over the clauses and the linked list of tests in lockstep,
 | 
|    // translating the clause bodies.
 | 
| -  HBasicBlock* curr_test_block = first_test_block;
 | 
|    HBasicBlock* fall_through_block = NULL;
 | 
|  
 | 
|    BreakAndContinueInfo break_info(stmt);
 | 
| @@ -4235,40 +4249,16 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
 | 
|        // goes to.
 | 
|        HBasicBlock* normal_block = NULL;
 | 
|        if (clause->is_default()) {
 | 
| -        if (last_block != NULL) {
 | 
| -          normal_block = last_block;
 | 
| -          last_block = NULL;  // Cleared to indicate we've handled it.
 | 
| -        }
 | 
| +        if (last_block == NULL) continue;
 | 
| +        normal_block = last_block;
 | 
| +        last_block = NULL;  // Cleared to indicate we've handled it.
 | 
|        } else {
 | 
| -        // If the current test block is deoptimizing due to an unhandled clause
 | 
| -        // of the switch, the test instruction is in the next block since the
 | 
| -        // deopt must end the current block.
 | 
| -        if (curr_test_block->IsDeoptimizing()) {
 | 
| -          ASSERT(curr_test_block->end()->SecondSuccessor() == NULL);
 | 
| -          curr_test_block = curr_test_block->end()->FirstSuccessor();
 | 
| -        }
 | 
| -        normal_block = curr_test_block->end()->FirstSuccessor();
 | 
| -        curr_test_block = curr_test_block->end()->SecondSuccessor();
 | 
| +        normal_block = body_blocks[i];
 | 
|        }
 | 
|  
 | 
| -      // Identify a block to emit the body into.
 | 
| -      if (normal_block == NULL) {
 | 
| -        if (fall_through_block == NULL) {
 | 
| -          // (a) Unreachable.
 | 
| -          if (clause->is_default()) {
 | 
| -            continue;  // Might still be reachable clause bodies.
 | 
| -          } else {
 | 
| -            break;
 | 
| -          }
 | 
| -        } else {
 | 
| -          // (b) Reachable only as fall through.
 | 
| -          set_current_block(fall_through_block);
 | 
| -        }
 | 
| -      } else if (fall_through_block == NULL) {
 | 
| -        // (c) Reachable only normally.
 | 
| +      if (fall_through_block == NULL) {
 | 
|          set_current_block(normal_block);
 | 
|        } else {
 | 
| -        // (d) Reachable both ways.
 | 
|          HBasicBlock* join = CreateJoin(fall_through_block,
 | 
|                                         normal_block,
 | 
|                                         clause->EntryId());
 | 
| 
 |