/*
- * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
continue;
ASSERT(block->isReachable);
- switch (block->last()->op()) {
+ switch (block->terminal()->op()) {
case Jump: {
// Successor with one predecessor -> merge.
if (block->successor(0)->predecessors.size() == 1) {
if (extremeLogging)
m_graph.dump();
m_graph.dethread();
-
- ASSERT(block->last()->isTerminal());
- NodeOrigin boundaryNodeOrigin = block->last()->origin;
- block->last()->convertToPhantom();
- ASSERT(block->last()->refCount() == 1);
-
+
+ Node* terminal = block->terminal();
+ ASSERT(terminal->isTerminal());
+ NodeOrigin boundaryNodeOrigin = terminal->origin;
+
jettisonBlock(block, jettisonedBlock, boundaryNodeOrigin);
-
- block->appendNode(
+
+ block->replaceTerminal(
m_graph, SpecNone, Jump, boundaryNodeOrigin,
OpInfo(targetBlock));
+
+ ASSERT(block->terminal());
+
}
innerChanged = outerChanged = true;
break;
}
case Switch: {
- SwitchData* data = block->last()->switchData();
+ SwitchData* data = block->terminal()->switchData();
// Prune out cases that end up jumping to default.
for (unsigned i = 0; i < data->cases.size(); ++i) {
}
// Switch on constant -> jettison all other targets and merge.
- if (block->last()->child1()->hasConstant()) {
- JSValue value = m_graph.valueOfJSConstant(block->last()->child1().node());
+ Node* terminal = block->terminal();
+ if (terminal->child1()->hasConstant()) {
+ FrozenValue* value = terminal->child1()->constant();
TriState found = FalseTriState;
BasicBlock* targetBlock = 0;
for (unsigned i = data->cases.size(); found == FalseTriState && i--;) {
ASSERT(targetBlock);
Vector<BasicBlock*, 1> jettisonedBlocks;
- for (unsigned i = block->numSuccessors(); i--;) {
- BasicBlock* jettisonedBlock = block->successor(i);
- if (jettisonedBlock != targetBlock)
- jettisonedBlocks.append(jettisonedBlock);
+ for (BasicBlock* successor : terminal->successors()) {
+ if (successor != targetBlock)
+ jettisonedBlocks.append(successor);
}
if (targetBlock->predecessors.size() == 1) {
m_graph.dump();
m_graph.dethread();
- NodeOrigin boundaryNodeOrigin = block->last()->origin;
- block->last()->convertToPhantom();
+ NodeOrigin boundaryNodeOrigin = terminal->origin;
+
for (unsigned i = jettisonedBlocks.size(); i--;)
jettisonBlock(block, jettisonedBlocks[i], boundaryNodeOrigin);
- block->appendNode(
+
+ block->replaceTerminal(
m_graph, SpecNone, Jump, boundaryNodeOrigin, OpInfo(targetBlock));
}
innerChanged = outerChanged = true;
m_graph.dethread();
mergeBlocks(block, targetBlock, noBlocks());
} else {
- Node* branch = block->last();
- ASSERT(branch->isTerminal());
+ Node* branch = block->terminal();
ASSERT(branch->op() == Branch || branch->op() == Switch);
- branch->convertToPhantom();
- ASSERT(branch->refCount() == 1);
-
- block->appendNode(
+
+ block->replaceTerminal(
m_graph, SpecNone, Jump, branch->origin, OpInfo(targetBlock));
}
}
NodeType nodeType;
if (livenessNode->flags() & NodeIsFlushed)
nodeType = Flush;
- else
+ else {
+ // This seems like it shouldn't be necessary because we could just rematerialize
+ // PhantomLocals or something similar using bytecode liveness. However, in ThreadedCPS, it's
+ // worth the sanity to maintain this eagerly. See
+ // https://bugs.webkit.org/show_bug.cgi?id=144086
nodeType = PhantomLocal;
+ }
block->appendNode(
m_graph, SpecNone, nodeType, nodeOrigin,
OpInfo(livenessNode->variableAccessData()));
// kept alive.
// Remove the terminal of firstBlock since we don't need it anymore. Well, we don't
- // really remove it; we actually turn it into a Phantom.
- ASSERT(firstBlock->last()->isTerminal());
- NodeOrigin boundaryNodeOrigin = firstBlock->last()->origin;
- firstBlock->last()->convertToPhantom();
- ASSERT(firstBlock->last()->refCount() == 1);
+ // really remove it; we actually turn it into a check.
+ Node* terminal = firstBlock->terminal();
+ ASSERT(terminal->isTerminal());
+ NodeOrigin boundaryNodeOrigin = terminal->origin;
+ terminal->remove();
+ ASSERT(terminal->refCount() == 1);
for (unsigned i = jettisonedBlocks.size(); i--;) {
BasicBlock* jettisonedBlock = jettisonedBlocks[i];
for (size_t i = 0; i < secondBlock->size(); ++i)
firstBlock->append(secondBlock->at(i));
- ASSERT(firstBlock->last()->isTerminal());
+ ASSERT(firstBlock->terminal()->isTerminal());
// Fix the predecessors of my new successors. This is tricky, since we are going to reset
// all predecessors anyway due to reachability analysis. But we need to fix the