| Index: src/compiler/instruction-selector.cc | 
| diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc | 
| index 11f455cfbb4c74b1d18114d651b8c2edb55d0983..75fc35560a18fa80e6a37b549d63ccde0ea19260 100644 | 
| --- a/src/compiler/instruction-selector.cc | 
| +++ b/src/compiler/instruction-selector.cc | 
| @@ -483,7 +483,9 @@ void InstructionSelector::VisitBlock(BasicBlock* block) { | 
| } | 
|  | 
|  | 
| -static inline void CheckNoPhis(const BasicBlock* block) { | 
| +namespace { | 
| + | 
| +V8_INLINE void CheckNoPhis(const BasicBlock* block) { | 
| #ifdef DEBUG | 
| // Branch targets should not have phis. | 
| for (BasicBlock::const_iterator i = block->begin(); i != block->end(); ++i) { | 
| @@ -493,6 +495,8 @@ static inline void CheckNoPhis(const BasicBlock* block) { | 
| #endif | 
| } | 
|  | 
| +}  // namespace | 
| + | 
|  | 
| void InstructionSelector::VisitControl(BasicBlock* block) { | 
| Node* input = block->control_input(); | 
| @@ -513,6 +517,18 @@ void InstructionSelector::VisitControl(BasicBlock* block) { | 
| if (condition->opcode() == IrOpcode::kAlways) return VisitGoto(tbranch); | 
| return VisitBranch(input, tbranch, fbranch); | 
| } | 
| +    case BasicBlock::kSwitch: { | 
| +      DCHECK_EQ(IrOpcode::kSwitch, input->opcode()); | 
| +      BasicBlock** const branches = &block->successors().front(); | 
| +      size_t const branch_count = block->SuccessorCount(); | 
| +      DCHECK_LE(2u, branch_count); | 
| +      // SSA deconstruction requires targets of branches not to have phis. | 
| +      // Edge split form guarantees this property, but is more strict. | 
| +      for (size_t index = 0; index < branch_count; ++index) { | 
| +        CheckNoPhis(branches[index]); | 
| +      } | 
| +      return VisitSwitch(input, branches, branch_count); | 
| +    } | 
| case BasicBlock::kReturn: { | 
| // If the result itself is a return, return its input. | 
| Node* value = (input != NULL && input->opcode() == IrOpcode::kReturn) | 
| @@ -525,7 +541,7 @@ void InstructionSelector::VisitControl(BasicBlock* block) { | 
| return VisitThrow(input->InputAt(0)); | 
| case BasicBlock::kNone: { | 
| // TODO(titzer): exit block doesn't have control. | 
| -      DCHECK(input == NULL); | 
| +      DCHECK_NULL(input); | 
| break; | 
| } | 
| default: | 
| @@ -544,6 +560,8 @@ MachineType InstructionSelector::GetMachineType(Node* node) { | 
| case IrOpcode::kBranch: | 
| case IrOpcode::kIfTrue: | 
| case IrOpcode::kIfFalse: | 
| +    case IrOpcode::kSwitch: | 
| +    case IrOpcode::kCase: | 
| case IrOpcode::kEffectPhi: | 
| case IrOpcode::kEffectSet: | 
| case IrOpcode::kMerge: | 
| @@ -682,6 +700,8 @@ void InstructionSelector::VisitNode(Node* node) { | 
| case IrOpcode::kBranch: | 
| case IrOpcode::kIfTrue: | 
| case IrOpcode::kIfFalse: | 
| +    case IrOpcode::kSwitch: | 
| +    case IrOpcode::kCase: | 
| case IrOpcode::kEffectPhi: | 
| case IrOpcode::kMerge: | 
| // No code needed for these graph artifacts. | 
| @@ -1038,6 +1058,22 @@ void InstructionSelector::VisitGoto(BasicBlock* target) { | 
| } | 
|  | 
|  | 
| +void InstructionSelector::VisitSwitch(Node* node, BasicBlock** branches, | 
| +                                      size_t branch_count) { | 
| +  OperandGenerator g(this); | 
| +  Node* const value = node->InputAt(0); | 
| +  size_t const input_count = branch_count + 1; | 
| +  InstructionOperand* const inputs = | 
| +      zone()->NewArray<InstructionOperand>(static_cast<int>(input_count)); | 
| +  inputs[0] = g.UseRegister(value); | 
| +  for (size_t index = 0; index < branch_count; ++index) { | 
| +    inputs[index + 1] = g.Label(branches[index]); | 
| +  } | 
| +  Emit(kArchSwitch, 0, nullptr, input_count, inputs, 0, nullptr) | 
| +      ->MarkAsControl(); | 
| +} | 
| + | 
| + | 
| void InstructionSelector::VisitReturn(Node* value) { | 
| OperandGenerator g(this); | 
| if (value != NULL) { | 
|  |