| 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.
 | 
| 
 |