diff options
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGGraph.h')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGGraph.h | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h index fdb78cf9b..8d164a299 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.h +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -76,11 +76,13 @@ struct ResolveGlobalData { // Nodes that are 'dead' remain in the vector with refCount 0. class Graph : public Vector<Node, 64> { public: - Graph(JSGlobalData& globalData, CodeBlock* codeBlock) + Graph(JSGlobalData& globalData, CodeBlock* codeBlock, unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues) : m_globalData(globalData) , m_codeBlock(codeBlock) , m_profiledBlock(codeBlock->alternative()) , m_hasArguments(false) + , m_osrEntryBytecodeIndex(osrEntryBytecodeIndex) + , m_mustHandleValues(mustHandleValues) { ASSERT(m_profiledBlock); } @@ -137,6 +139,20 @@ public: 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 +630,69 @@ public: 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; @@ -633,6 +712,8 @@ public: Dominators m_dominators; unsigned m_localVars; unsigned m_parameterSlots; + unsigned m_osrEntryBytecodeIndex; + Operands<JSValue> m_mustHandleValues; private: void handleSuccessor(Vector<BlockIndex, 16>& worklist, BlockIndex blockIndex, BlockIndex successorIndex); |