Chromium Code Reviews| Index: src/compiler/scheduler.cc |
| diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc |
| index 25bdba4961cc6c79fb39d716859dceccc301dc62..9d918afb552593667ff6ddc25301249c5cf40c55 100644 |
| --- a/src/compiler/scheduler.cc |
| +++ b/src/compiler/scheduler.cc |
| @@ -286,7 +286,7 @@ class CFGBuilder : public ZoneObject { |
| } |
| private: |
| - // TODO(mstarzinger): Only for Scheduler::FuseFloatingControl. |
| + friend class ScheduleLateNodeVisitor; |
| friend class Scheduler; |
| void FixNode(BasicBlock* block, Node* node) { |
| @@ -320,6 +320,10 @@ class CFGBuilder : public ZoneObject { |
| case IrOpcode::kSwitch: |
| BuildBlocksForSuccessors(node); |
| break; |
| + case IrOpcode::kCall: |
| + if (!IsExceptionalCall(node)) break; |
|
titzer
2015/02/17 10:32:52
Flip condition?
Michael Starzinger
2015/02/17 10:58:30
Done.
|
| + BuildBlocksForSuccessors(node); |
| + break; |
| default: |
| break; |
| } |
| @@ -347,6 +351,11 @@ class CFGBuilder : public ZoneObject { |
| scheduler_->UpdatePlacement(node, Scheduler::kFixed); |
| ConnectThrow(node); |
| break; |
| + case IrOpcode::kCall: |
| + if (!IsExceptionalCall(node)) break; |
|
titzer
2015/02/17 10:32:52
Same.
Michael Starzinger
2015/02/17 10:58:29
Done.
|
| + scheduler_->UpdatePlacement(node, Scheduler::kFixed); |
| + ConnectCall(node); |
| + break; |
| default: |
| break; |
| } |
| @@ -373,19 +382,16 @@ class CFGBuilder : public ZoneObject { |
| } |
| // Collect the branch-related projections from a node, such as IfTrue, |
| - // IfFalse, and Case. |
| + // IfFalse, IfException, IfSuccess, and Case. |
| void CollectSuccessorProjections(Node* node, Node** successors, |
| size_t successor_count) { |
| #ifdef DEBUG |
| - DCHECK_EQ(static_cast<int>(successor_count), node->UseCount()); |
| + DCHECK_LE(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; |
| @@ -394,10 +400,20 @@ class CFGBuilder : public ZoneObject { |
| DCHECK_EQ(IrOpcode::kBranch, node->opcode()); |
| index = 1; |
| break; |
| + case IrOpcode::kIfException: |
| + DCHECK_EQ(IrOpcode::kCall, node->opcode()); |
| + index = 1; |
| + break; |
| + case IrOpcode::kIfSuccess: |
| + DCHECK_EQ(IrOpcode::kCall, node->opcode()); |
| + index = 0; |
| + break; |
| case IrOpcode::kCase: |
| DCHECK_EQ(IrOpcode::kSwitch, node->opcode()); |
| index = CaseIndexOf(use->op()); |
| break; |
| + default: |
| + continue; |
| } |
| DCHECK_LT(index, successor_count); |
| DCHECK(successors[index] == nullptr); |
| @@ -419,6 +435,31 @@ class CFGBuilder : public ZoneObject { |
| } |
| } |
| + BasicBlock* FindPredecessorBlock(Node* node) { |
| + BasicBlock* predecessor_block = nullptr; |
| + while (true) { |
| + predecessor_block = schedule_->block(node); |
| + if (predecessor_block != nullptr) break; |
| + node = NodeProperties::GetControlInput(node); |
| + } |
| + return predecessor_block; |
| + } |
| + |
| + void ConnectCall(Node* call) { |
| + BasicBlock* successor_blocks[2]; |
| + CollectSuccessorBlocks(call, successor_blocks, arraysize(successor_blocks)); |
| + |
| + // Consider the exception continuation to be deferred. |
| + successor_blocks[1]->set_deferred(true); |
| + |
| + Node* call_control = NodeProperties::GetControlInput(call); |
| + BasicBlock* call_block = FindPredecessorBlock(call_control); |
| + TraceConnect(call, call_block, successor_blocks[0]); |
| + TraceConnect(call, call_block, successor_blocks[1]); |
| + schedule_->AddCall(call_block, call, successor_blocks[0], |
| + successor_blocks[1]); |
| + } |
| + |
| void ConnectBranch(Node* branch) { |
| BasicBlock* successor_blocks[2]; |
| CollectSuccessorBlocks(branch, successor_blocks, |
| @@ -442,10 +483,8 @@ class CFGBuilder : public ZoneObject { |
| schedule_->InsertBranch(component_start_, component_end_, branch, |
| successor_blocks[0], successor_blocks[1]); |
| } else { |
| - Node* branch_block_node = NodeProperties::GetControlInput(branch); |
| - BasicBlock* branch_block = schedule_->block(branch_block_node); |
| - DCHECK_NOT_NULL(branch_block); |
| - |
| + Node* branch_control = NodeProperties::GetControlInput(branch); |
| + BasicBlock* branch_block = FindPredecessorBlock(branch_control); |
| TraceConnect(branch, branch_block, successor_blocks[0]); |
| TraceConnect(branch, branch_block, successor_blocks[1]); |
| schedule_->AddBranch(branch_block, branch, successor_blocks[0], |
| @@ -466,14 +505,12 @@ class CFGBuilder : public ZoneObject { |
| 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); |
| - |
| + Node* switch_control = NodeProperties::GetControlInput(sw); |
| + BasicBlock* switch_block = FindPredecessorBlock(switch_control); |
| for (size_t index = 0; index < successor_count; ++index) { |
| - TraceConnect(sw, sw_block, successor_blocks[index]); |
| + TraceConnect(sw, switch_block, successor_blocks[index]); |
| } |
| - schedule_->AddSwitch(sw_block, sw, successor_blocks, successor_count); |
| + schedule_->AddSwitch(switch_block, sw, successor_blocks, successor_count); |
| } |
| } |
| @@ -486,22 +523,22 @@ class CFGBuilder : public ZoneObject { |
| // 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()) { |
| - BasicBlock* predecessor_block = schedule_->block(input); |
| + BasicBlock* predecessor_block = FindPredecessorBlock(input); |
| TraceConnect(merge, predecessor_block, block); |
| schedule_->AddGoto(predecessor_block, block); |
| } |
| } |
| void ConnectReturn(Node* ret) { |
| - Node* return_block_node = NodeProperties::GetControlInput(ret); |
| - BasicBlock* return_block = schedule_->block(return_block_node); |
| + Node* return_control = NodeProperties::GetControlInput(ret); |
| + BasicBlock* return_block = FindPredecessorBlock(return_control); |
| TraceConnect(ret, return_block, NULL); |
| schedule_->AddReturn(return_block, ret); |
| } |
| void ConnectThrow(Node* thr) { |
| - Node* throw_block_node = NodeProperties::GetControlInput(thr); |
| - BasicBlock* throw_block = schedule_->block(throw_block_node); |
| + Node* throw_control = NodeProperties::GetControlInput(thr); |
| + BasicBlock* throw_block = FindPredecessorBlock(throw_control); |
| TraceConnect(thr, throw_block, NULL); |
| schedule_->AddThrow(throw_block, thr); |
| } |
| @@ -517,6 +554,13 @@ class CFGBuilder : public ZoneObject { |
| } |
| } |
| + bool IsExceptionalCall(Node* node) { |
| + for (Node* const use : node->uses()) { |
| + if (use->opcode() == IrOpcode::kIfException) return true; |
| + } |
| + return false; |
| + } |
| + |
| bool IsFinalMerge(Node* node) { |
| return (node->opcode() == IrOpcode::kMerge && |
| node == scheduler_->graph_->end()->InputAt(0)); |
| @@ -1362,7 +1406,7 @@ class ScheduleLateNodeVisitor { |
| } |
| // Schedule the node or a floating control structure. |
| - if (NodeProperties::IsControl(node)) { |
| + if (IrOpcode::IsMergeOpcode(node->opcode())) { |
| ScheduleFloatingControl(block, node); |
| } else { |
| ScheduleNode(block, node); |
| @@ -1486,10 +1530,13 @@ class ScheduleLateNodeVisitor { |
| return block; |
| } |
| + BasicBlock* FindPredecessorBlock(Node* node) { |
| + return scheduler_->control_flow_builder_->FindPredecessorBlock(node); |
| + } |
| + |
| BasicBlock* GetBlockForUse(Edge edge) { |
| Node* use = edge.from(); |
| - IrOpcode::Value opcode = use->opcode(); |
| - if (IrOpcode::IsPhiOpcode(opcode)) { |
| + if (IrOpcode::IsPhiOpcode(use->opcode())) { |
| // If the use is from a coupled (i.e. floating) phi, compute the common |
| // dominator of its uses. This will not recurse more than one level. |
| if (scheduler_->GetPlacement(use) == Scheduler::kCoupled) { |
| @@ -1498,15 +1545,23 @@ class ScheduleLateNodeVisitor { |
| DCHECK_EQ(edge.to(), NodeProperties::GetControlInput(use)); |
| return GetCommonDominatorOfUses(use); |
| } |
| - // If the use is from a fixed (i.e. non-floating) phi, use the block |
| - // of the corresponding control input to the merge. |
| + // If the use is from a fixed (i.e. non-floating) phi, we use the |
| + // predecessor block of the corresponding control input to the merge. |
| if (scheduler_->GetPlacement(use) == Scheduler::kFixed) { |
| Trace(" input@%d into a fixed phi #%d:%s\n", edge.index(), use->id(), |
| use->op()->mnemonic()); |
| Node* merge = NodeProperties::GetControlInput(use, 0); |
| - opcode = merge->opcode(); |
| - DCHECK(opcode == IrOpcode::kMerge || opcode == IrOpcode::kLoop); |
| - use = NodeProperties::GetControlInput(merge, edge.index()); |
| + DCHECK(IrOpcode::IsMergeOpcode(merge->opcode())); |
| + Node* input = NodeProperties::GetControlInput(merge, edge.index()); |
| + return FindPredecessorBlock(input); |
| + } |
| + } else if (IrOpcode::IsMergeOpcode(use->opcode())) { |
| + // If the use is from a fixed (i.e. non-floating) merge, we use the |
| + // predecessor block of the current input to the merge. |
| + if (scheduler_->GetPlacement(use) == Scheduler::kFixed) { |
| + Trace(" input@%d into a fixed merge #%d:%s\n", edge.index(), use->id(), |
| + use->op()->mnemonic()); |
| + return FindPredecessorBlock(edge.to()); |
| } |
| } |
| BasicBlock* result = schedule_->block(use); |