summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/schedule.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/schedule.cc')
-rw-r--r--deps/v8/src/compiler/schedule.cc111
1 files changed, 87 insertions, 24 deletions
diff --git a/deps/v8/src/compiler/schedule.cc b/deps/v8/src/compiler/schedule.cc
index 4ac65e5ae4..6bd1a17be0 100644
--- a/deps/v8/src/compiler/schedule.cc
+++ b/deps/v8/src/compiler/schedule.cc
@@ -199,11 +199,28 @@ void Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) {
AddSuccessor(block, succ);
}
+#if DEBUG
+namespace {
+
+bool IsPotentiallyThrowingCall(IrOpcode::Value opcode) {
+ switch (opcode) {
+#define BUILD_BLOCK_JS_CASE(Name) case IrOpcode::k##Name:
+ JS_OP_LIST(BUILD_BLOCK_JS_CASE)
+#undef BUILD_BLOCK_JS_CASE
+ case IrOpcode::kCall:
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace
+#endif // DEBUG
void Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
BasicBlock* exception_block) {
DCHECK_EQ(BasicBlock::kNone, block->control());
- DCHECK_EQ(IrOpcode::kCall, call->opcode());
+ DCHECK(IsPotentiallyThrowingCall(call->opcode()));
block->set_control(BasicBlock::kCall);
AddSuccessor(block, success_block);
AddSuccessor(block, exception_block);
@@ -298,41 +315,87 @@ void Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
SetControlInput(block, sw);
}
-void Schedule::EnsureSplitEdgeForm() {
+void Schedule::EnsureCFGWellFormedness() {
// Make a copy of all the blocks for the iteration, since adding the split
// edges will allocate new blocks.
BasicBlockVector all_blocks_copy(all_blocks_);
// Insert missing split edge blocks.
for (auto block : all_blocks_copy) {
- if (block->PredecessorCount() > 1 && block != end_) {
- for (auto current_pred = block->predecessors().begin();
- current_pred != block->predecessors().end(); ++current_pred) {
- BasicBlock* pred = *current_pred;
- if (pred->SuccessorCount() > 1) {
- // Found a predecessor block with multiple successors.
- BasicBlock* split_edge_block = NewBasicBlock();
- split_edge_block->set_control(BasicBlock::kGoto);
- split_edge_block->successors().push_back(block);
- split_edge_block->predecessors().push_back(pred);
- split_edge_block->set_deferred(pred->deferred());
- *current_pred = split_edge_block;
- // Find a corresponding successor in the previous block, replace it
- // with the split edge block... but only do it once, since we only
- // replace the previous blocks in the current block one at a time.
- for (auto successor = pred->successors().begin();
- successor != pred->successors().end(); ++successor) {
- if (*successor == block) {
- *successor = split_edge_block;
- break;
- }
- }
+ if (block->PredecessorCount() > 1) {
+ if (block != end_) {
+ EnsureSplitEdgeForm(block);
+ }
+ if (block->deferred()) {
+ EnsureDeferredCodeSingleEntryPoint(block);
+ }
+ }
+ }
+}
+
+void Schedule::EnsureSplitEdgeForm(BasicBlock* block) {
+ DCHECK(block->PredecessorCount() > 1 && block != end_);
+ for (auto current_pred = block->predecessors().begin();
+ current_pred != block->predecessors().end(); ++current_pred) {
+ BasicBlock* pred = *current_pred;
+ if (pred->SuccessorCount() > 1) {
+ // Found a predecessor block with multiple successors.
+ BasicBlock* split_edge_block = NewBasicBlock();
+ split_edge_block->set_control(BasicBlock::kGoto);
+ split_edge_block->successors().push_back(block);
+ split_edge_block->predecessors().push_back(pred);
+ split_edge_block->set_deferred(pred->deferred());
+ *current_pred = split_edge_block;
+ // Find a corresponding successor in the previous block, replace it
+ // with the split edge block... but only do it once, since we only
+ // replace the previous blocks in the current block one at a time.
+ for (auto successor = pred->successors().begin();
+ successor != pred->successors().end(); ++successor) {
+ if (*successor == block) {
+ *successor = split_edge_block;
+ break;
}
}
}
}
}
+void Schedule::EnsureDeferredCodeSingleEntryPoint(BasicBlock* block) {
+ // If a deferred block has multiple predecessors, they have to
+ // all be deferred. Otherwise, we can run into a situation where a range
+ // that spills only in deferred blocks inserts its spill in the block, but
+ // other ranges need moves inserted by ResolveControlFlow in the predecessors,
+ // which may clobber the register of this range.
+ // To ensure that, when a deferred block has multiple predecessors, and some
+ // are not deferred, we add a non-deferred block to collect all such edges.
+
+ DCHECK(block->deferred() && block->PredecessorCount() > 1);
+ bool all_deferred = true;
+ for (auto current_pred = block->predecessors().begin();
+ current_pred != block->predecessors().end(); ++current_pred) {
+ BasicBlock* pred = *current_pred;
+ if (!pred->deferred()) {
+ all_deferred = false;
+ break;
+ }
+ }
+
+ if (all_deferred) return;
+ BasicBlock* merger = NewBasicBlock();
+ merger->set_control(BasicBlock::kGoto);
+ merger->successors().push_back(block);
+ for (auto current_pred = block->predecessors().begin();
+ current_pred != block->predecessors().end(); ++current_pred) {
+ BasicBlock* pred = *current_pred;
+ merger->predecessors().push_back(pred);
+ pred->successors().clear();
+ pred->successors().push_back(merger);
+ }
+ merger->set_deferred(false);
+ block->predecessors().clear();
+ block->predecessors().push_back(merger);
+}
+
void Schedule::PropagateDeferredMark() {
// Push forward the deferred block marks through newly inserted blocks and
// other improperly marked blocks until a fixed point is reached.