| Index: src/compiler/scheduler.cc | 
| diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc | 
| index 2e12dd36af6a3bf25d2af21634efd7808ff86d94..555625691723db9b9e754931896c28fd51120915 100644 | 
| --- a/src/compiler/scheduler.cc | 
| +++ b/src/compiler/scheduler.cc | 
| @@ -218,7 +218,8 @@ void Scheduler::DecrementUnscheduledUseCount(Node* node, int index, | 
| class CFGBuilder : public ZoneObject { | 
| public: | 
| CFGBuilder(Zone* zone, Scheduler* scheduler) | 
| -      : scheduler_(scheduler), | 
| +      : zone_(zone), | 
| +        scheduler_(scheduler), | 
| schedule_(scheduler->schedule_), | 
| queued_(scheduler->graph_, 2), | 
| queue_(zone), | 
| @@ -316,7 +317,8 @@ class CFGBuilder : public ZoneObject { | 
| BuildBlockForNode(node); | 
| break; | 
| case IrOpcode::kBranch: | 
| -        BuildBlocksForSuccessors(node, IrOpcode::kIfTrue, IrOpcode::kIfFalse); | 
| +      case IrOpcode::kSwitch: | 
| +        BuildBlocksForSuccessors(node); | 
| break; | 
| default: | 
| break; | 
| @@ -333,6 +335,10 @@ class CFGBuilder : public ZoneObject { | 
| scheduler_->UpdatePlacement(node, Scheduler::kFixed); | 
| ConnectBranch(node); | 
| break; | 
| +      case IrOpcode::kSwitch: | 
| +        scheduler_->UpdatePlacement(node, Scheduler::kFixed); | 
| +        ConnectSwitch(node); | 
| +        break; | 
| case IrOpcode::kReturn: | 
| scheduler_->UpdatePlacement(node, Scheduler::kFixed); | 
| ConnectReturn(node); | 
| @@ -357,49 +363,67 @@ class CFGBuilder : public ZoneObject { | 
| return block; | 
| } | 
|  | 
| -  void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a, | 
| -                                IrOpcode::Value b) { | 
| -    Node* successors[2]; | 
| -    CollectSuccessorProjections(node, successors, a, b); | 
| -    BuildBlockForNode(successors[0]); | 
| -    BuildBlockForNode(successors[1]); | 
| +  void BuildBlocksForSuccessors(Node* node) { | 
| +    size_t const successor_count = node->op()->ControlOutputCount(); | 
| +    Node** successors = | 
| +        zone_->NewArray<Node*>(static_cast<int>(successor_count)); | 
| +    CollectSuccessorProjections(node, successors, successor_count); | 
| +    for (size_t index = 0; index < successor_count; ++index) { | 
| +      BuildBlockForNode(successors[index]); | 
| +    } | 
| } | 
|  | 
| // Collect the branch-related projections from a node, such as IfTrue, | 
| -  // IfFalse. | 
| -  // TODO(titzer): consider moving this to node.h | 
| -  void CollectSuccessorProjections(Node* node, Node** buffer, | 
| -                                   IrOpcode::Value true_opcode, | 
| -                                   IrOpcode::Value false_opcode) { | 
| -    buffer[0] = NULL; | 
| -    buffer[1] = NULL; | 
| -    for (Node* use : node->uses()) { | 
| -      if (use->opcode() == true_opcode) { | 
| -        DCHECK(!buffer[0]); | 
| -        buffer[0] = use; | 
| -      } | 
| -      if (use->opcode() == false_opcode) { | 
| -        DCHECK(!buffer[1]); | 
| -        buffer[1] = use; | 
| +  // IfFalse, and Case. | 
| +  void CollectSuccessorProjections(Node* node, Node** successors, | 
| +                                   size_t successor_count) { | 
| +#ifdef DEBUG | 
| +    DCHECK_EQ(static_cast<int>(successor_count), node->UseCount()); | 
| +    std::memset(successors, 0, sizeof(*successors) * successor_count); | 
| +#endif | 
| +    for (Node* const use : node->uses()) { | 
| +      size_t index; | 
| +      switch (use->opcode()) { | 
| +        default: | 
| +          UNREACHABLE(); | 
| +        // Fall through. | 
| +        case IrOpcode::kIfTrue: | 
| +          DCHECK_EQ(IrOpcode::kBranch, node->opcode()); | 
| +          index = 0; | 
| +          break; | 
| +        case IrOpcode::kIfFalse: | 
| +          DCHECK_EQ(IrOpcode::kBranch, node->opcode()); | 
| +          index = 1; | 
| +          break; | 
| +        case IrOpcode::kCase: | 
| +          DCHECK_EQ(IrOpcode::kSwitch, node->opcode()); | 
| +          index = CaseIndexOf(use->op()); | 
| +          break; | 
| } | 
| +      DCHECK_LT(index, successor_count); | 
| +      DCHECK(successors[index] == nullptr); | 
| +      successors[index] = use; | 
| +    } | 
| +#ifdef DEBUG | 
| +    for (size_t index = 0; index < successor_count; ++index) { | 
| +      DCHECK_NOT_NULL(successors[index]); | 
| } | 
| -    DCHECK(buffer[0]); | 
| -    DCHECK(buffer[1]); | 
| +#endif | 
| } | 
|  | 
| -  void CollectSuccessorBlocks(Node* node, BasicBlock** buffer, | 
| -                              IrOpcode::Value true_opcode, | 
| -                              IrOpcode::Value false_opcode) { | 
| -    Node* successors[2]; | 
| -    CollectSuccessorProjections(node, successors, true_opcode, false_opcode); | 
| -    buffer[0] = schedule_->block(successors[0]); | 
| -    buffer[1] = schedule_->block(successors[1]); | 
| +  void CollectSuccessorBlocks(Node* node, BasicBlock** successor_blocks, | 
| +                              size_t successor_count) { | 
| +    Node** successors = reinterpret_cast<Node**>(successor_blocks); | 
| +    CollectSuccessorProjections(node, successors, successor_count); | 
| +    for (size_t index = 0; index < successor_count; ++index) { | 
| +      successor_blocks[index] = schedule_->block(successors[index]); | 
| +    } | 
| } | 
|  | 
| void ConnectBranch(Node* branch) { | 
| BasicBlock* successor_blocks[2]; | 
| -    CollectSuccessorBlocks(branch, successor_blocks, IrOpcode::kIfTrue, | 
| -                           IrOpcode::kIfFalse); | 
| +    CollectSuccessorBlocks(branch, successor_blocks, | 
| +                           arraysize(successor_blocks)); | 
|  | 
| // Consider branch hints. | 
| switch (BranchHintOf(branch->op())) { | 
| @@ -421,7 +445,7 @@ class CFGBuilder : public ZoneObject { | 
| } else { | 
| Node* branch_block_node = NodeProperties::GetControlInput(branch); | 
| BasicBlock* branch_block = schedule_->block(branch_block_node); | 
| -      DCHECK(branch_block != NULL); | 
| +      DCHECK_NOT_NULL(branch_block); | 
|  | 
| TraceConnect(branch, branch_block, successor_blocks[0]); | 
| TraceConnect(branch, branch_block, successor_blocks[1]); | 
| @@ -430,12 +454,36 @@ class CFGBuilder : public ZoneObject { | 
| } | 
| } | 
|  | 
| +  void ConnectSwitch(Node* sw) { | 
| +    size_t const successor_count = sw->op()->ControlOutputCount(); | 
| +    BasicBlock** successor_blocks = | 
| +        zone_->NewArray<BasicBlock*>(static_cast<int>(successor_count)); | 
| +    CollectSuccessorBlocks(sw, successor_blocks, successor_count); | 
| + | 
| +    if (sw == component_entry_) { | 
| +      for (size_t index = 0; index < successor_count; ++index) { | 
| +        TraceConnect(sw, component_start_, successor_blocks[index]); | 
| +      } | 
| +      schedule_->InsertSwitch(component_start_, component_end_, sw, | 
| +                              successor_blocks, successor_count); | 
| +    } else { | 
| +      Node* sw_block_node = NodeProperties::GetControlInput(sw); | 
| +      BasicBlock* sw_block = schedule_->block(sw_block_node); | 
| +      DCHECK_NOT_NULL(sw_block); | 
| + | 
| +      for (size_t index = 0; index < successor_count; ++index) { | 
| +        TraceConnect(sw, sw_block, successor_blocks[index]); | 
| +      } | 
| +      schedule_->AddSwitch(sw_block, sw, successor_blocks, successor_count); | 
| +    } | 
| +  } | 
| + | 
| void ConnectMerge(Node* merge) { | 
| // Don't connect the special merge at the end to its predecessors. | 
| if (IsFinalMerge(merge)) return; | 
|  | 
| BasicBlock* block = schedule_->block(merge); | 
| -    DCHECK(block != NULL); | 
| +    DCHECK_NOT_NULL(block); | 
| // For all of the merge's control inputs, add a goto at the end to the | 
| // merge's basic block. | 
| for (Node* const input : merge->inputs()) { | 
| @@ -460,7 +508,7 @@ class CFGBuilder : public ZoneObject { | 
| } | 
|  | 
| void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) { | 
| -    DCHECK(block); | 
| +    DCHECK_NOT_NULL(block); | 
| if (succ == NULL) { | 
| Trace("Connect #%d:%s, B%d -> end\n", node->id(), node->op()->mnemonic(), | 
| block->id().ToInt()); | 
| @@ -487,6 +535,7 @@ class CFGBuilder : public ZoneObject { | 
| DCHECK(control_.empty()); | 
| } | 
|  | 
| +  Zone* zone_; | 
| Scheduler* scheduler_; | 
| Schedule* schedule_; | 
| NodeMarker<bool> queued_;      // Mark indicating whether node is queued. | 
|  |