Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (125822 => 125823)
--- trunk/Source/_javascript_Core/ChangeLog 2012-08-16 23:11:00 UTC (rev 125822)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-08-16 23:17:24 UTC (rev 125823)
@@ -1,5 +1,28 @@
2012-08-16 Filip Pizlo <[email protected]>
+ Structure check hoisting should be less expensive
+ https://bugs.webkit.org/show_bug.cgi?id=94201
+
+ Reviewed by Mark Hahnenberg.
+
+ This appears like a broad win on short-running programs.
+
+ * dfg/DFGArgumentsSimplificationPhase.cpp:
+ (JSC::DFG::ArgumentsSimplificationPhase::run):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGDriver.cpp:
+ (JSC::DFG::compile):
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::compareAndSwap):
+ (Graph):
+ (JSC::DFG::Graph::substitute):
+ (JSC::DFG::Graph::substituteGetLocal):
+ * dfg/DFGStructureCheckHoistingPhase.cpp:
+ (JSC::DFG::StructureCheckHoistingPhase::run):
+
+2012-08-16 Filip Pizlo <[email protected]>
+
All op_resolve_global instructions should end up in the list of global resolve instructions
https://bugs.webkit.org/show_bug.cgi?id=94247
<rdar://problem/12103500>
Modified: trunk/Source/_javascript_Core/dfg/DFGArgumentsSimplificationPhase.cpp (125822 => 125823)
--- trunk/Source/_javascript_Core/dfg/DFGArgumentsSimplificationPhase.cpp 2012-08-16 23:11:00 UTC (rev 125822)
+++ trunk/Source/_javascript_Core/dfg/DFGArgumentsSimplificationPhase.cpp 2012-08-16 23:17:24 UTC (rev 125823)
@@ -318,6 +318,7 @@
break;
case CheckStructure:
+ case ForwardCheckStructure:
case StructureTransitionWatchpoint:
// We don't care about these because if we get uses of the relevant
// variable then we can safely get rid of these, too. This of course
@@ -481,6 +482,7 @@
}
case CheckStructure:
+ case ForwardCheckStructure:
case StructureTransitionWatchpoint: {
// We can just get rid of this node, if it references a phantom argument.
if (!isOKToOptimize(m_graph[node.child1()]))
Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (125822 => 125823)
--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp 2012-08-16 23:11:00 UTC (rev 125822)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp 2012-08-16 23:17:24 UTC (rev 125823)
@@ -944,7 +944,7 @@
case GetLocal: {
VariableAccessData* variableAccessData = node.variableAccessData();
- if (m_fixpointState == FixpointNotConverged && !variableAccessData->isCaptured())
+ if (!variableAccessData->isCaptured())
break;
NodeIndex relevantLocalOp;
NodeIndex possibleReplacement = getLocalLoadElimination(variableAccessData->local(), relevantLocalOp, variableAccessData->isCaptured());
Modified: trunk/Source/_javascript_Core/dfg/DFGDriver.cpp (125822 => 125823)
--- trunk/Source/_javascript_Core/dfg/DFGDriver.cpp 2012-08-16 23:11:00 UTC (rev 125822)
+++ trunk/Source/_javascript_Core/dfg/DFGDriver.cpp 2012-08-16 23:17:24 UTC (rev 125823)
@@ -90,6 +90,7 @@
validate(dfg);
performPredictionPropagation(dfg);
performFixup(dfg);
+ performStructureCheckHoisting(dfg);
unsigned cnt = 1;
for (;; ++cnt) {
#if DFG_ENABLE(DEBUG_VERBOSE)
@@ -106,10 +107,7 @@
dfg.resetExitStates();
performFixup(dfg);
}
- bool shouldRedoCFA = performStructureCheckHoisting(dfg);
performCSE(dfg, FixpointConverged);
- if (shouldRedoCFA)
- performCFA(dfg);
#if DFG_ENABLE(DEBUG_VERBOSE)
dataLog("DFG optimization fixpoint converged in %u iterations.\n", cnt);
#endif
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.h (125822 => 125823)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.h 2012-08-16 23:11:00 UTC (rev 125822)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.h 2012-08-16 23:17:24 UTC (rev 125823)
@@ -137,6 +137,20 @@
edge = newEdge;
}
+ void compareAndSwap(Edge& edge, NodeIndex oldIndex, NodeIndex newIndex, bool changeRef)
+ {
+ if (edge.index() != oldIndex)
+ return;
+ changeIndex(edge, newIndex, changeRef);
+ }
+
+ void compareAndSwap(Edge& edge, Edge oldEdge, Edge newEdge, bool changeRef)
+ {
+ if (edge != oldEdge)
+ return;
+ changeEdge(edge, newEdge, changeRef);
+ }
+
void clearAndDerefChild1(Node& node)
{
if (!node.child1())
@@ -614,6 +628,69 @@
vote(node.child3(), ballot);
}
+ template<typename T> // T = NodeIndex or Edge
+ void substitute(BasicBlock& block, unsigned startIndexInBlock, T oldThing, T newThing)
+ {
+ for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
+ NodeIndex nodeIndex = block[indexInBlock];
+ Node& node = at(nodeIndex);
+ if (node.flags() & NodeHasVarArgs) {
+ for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); ++childIdx)
+ compareAndSwap(m_varArgChildren[childIdx], oldThing, newThing, node.shouldGenerate());
+ continue;
+ }
+ if (!node.child1())
+ continue;
+ compareAndSwap(node.children.child1(), oldThing, newThing, node.shouldGenerate());
+ if (!node.child2())
+ continue;
+ compareAndSwap(node.children.child2(), oldThing, newThing, node.shouldGenerate());
+ if (!node.child3())
+ continue;
+ compareAndSwap(node.children.child3(), oldThing, newThing, node.shouldGenerate());
+ }
+ }
+
+ // Use this if you introduce a new GetLocal and you know that you introduced it *before*
+ // any GetLocals in the basic block.
+ // FIXME: it may be appropriate, in the future, to generalize this to handle GetLocals
+ // introduced anywhere in the basic block.
+ void substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, NodeIndex newGetLocal)
+ {
+ if (variableAccessData->isCaptured()) {
+ // Let CSE worry about this one.
+ return;
+ }
+ for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
+ NodeIndex nodeIndex = block[indexInBlock];
+ Node& node = at(nodeIndex);
+ bool shouldContinue = true;
+ switch (node.op()) {
+ case SetLocal: {
+ if (node.local() == variableAccessData->local())
+ shouldContinue = false;
+ break;
+ }
+
+ case GetLocal: {
+ if (node.variableAccessData() != variableAccessData)
+ continue;
+ substitute(block, indexInBlock, nodeIndex, newGetLocal);
+ NodeIndex oldTailIndex = block.variablesAtTail.operand(variableAccessData->local());
+ if (oldTailIndex == nodeIndex)
+ block.variablesAtTail.operand(variableAccessData->local()) = newGetLocal;
+ shouldContinue = false;
+ break;
+ }
+
+ default:
+ break;
+ }
+ if (!shouldContinue)
+ break;
+ }
+ }
+
JSGlobalData& m_globalData;
CodeBlock* m_codeBlock;
CodeBlock* m_profiledBlock;
Modified: trunk/Source/_javascript_Core/dfg/DFGStructureCheckHoistingPhase.cpp (125822 => 125823)
--- trunk/Source/_javascript_Core/dfg/DFGStructureCheckHoistingPhase.cpp 2012-08-16 23:11:00 UTC (rev 125822)
+++ trunk/Source/_javascript_Core/dfg/DFGStructureCheckHoistingPhase.cpp 2012-08-16 23:17:24 UTC (rev 125823)
@@ -353,6 +353,8 @@
if (block->variablesAtTail.operand(variable->local()) == nodeIndex)
block->variablesAtTail.operand(variable->local()) = getLocalIndex;
+ m_graph.substituteGetLocal(*block, indexInBlock, variable, getLocalIndex);
+
changed = true;
break;
}