diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz |
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit.
Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp | 466 |
1 files changed, 47 insertions, 419 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp index 52cebf80f..c022fce2b 100644 --- a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,11 +29,12 @@ #if ENABLE(DFG_JIT) #include "DFGAbstractState.h" -#include "DFGBasicBlock.h" +#include "DFGBasicBlockInlines.h" #include "DFGGraph.h" #include "DFGInsertionSet.h" #include "DFGPhase.h" #include "DFGValidate.h" +#include "Operations.h" namespace JSC { namespace DFG { @@ -59,7 +60,7 @@ public: continue; ASSERT(block->isReachable); - switch (m_graph[block->last()].op()) { + switch (block->last()->op()) { case Jump: { // Successor with one predecessor -> merge. if (m_graph.m_blocks[m_graph.successor(block, 0)]->m_predecessors.size() == 1) { @@ -71,6 +72,7 @@ public: #endif if (extremeLogging) m_graph.dump(); + m_graph.dethread(); mergeBlocks(blockIndex, m_graph.successor(block, 0), NoBlock); innerChanged = outerChanged = true; break; @@ -112,6 +114,7 @@ public: #endif if (extremeLogging) m_graph.dump(); + m_graph.dethread(); mergeBlocks( blockIndex, m_graph.successorForCondition(block, condition), @@ -125,21 +128,20 @@ public: #endif if (extremeLogging) m_graph.dump(); + m_graph.dethread(); BlockIndex takenBlockIndex = m_graph.successorForCondition(block, condition); BlockIndex notTakenBlockIndex = m_graph.successorForCondition(block, !condition); - ASSERT(m_graph[block->last()].isTerminal()); - CodeOrigin boundaryCodeOrigin = m_graph[block->last()].codeOrigin; - m_graph[block->last()].setOpAndDefaultFlags(Phantom); - ASSERT(m_graph[block->last()].refCount() == 1); + ASSERT(block->last()->isTerminal()); + CodeOrigin boundaryCodeOrigin = block->last()->codeOrigin; + block->last()->convertToPhantom(); + ASSERT(block->last()->refCount() == 1); jettisonBlock(blockIndex, notTakenBlockIndex, boundaryCodeOrigin); - NodeIndex jumpNodeIndex = m_graph.size(); - Node jump(Jump, boundaryCodeOrigin, OpInfo(takenBlockIndex)); - jump.ref(); - m_graph.append(jump); - block->append(jumpNodeIndex); + block->appendNode( + m_graph, SpecNone, Jump, boundaryCodeOrigin, + OpInfo(takenBlockIndex)); } innerChanged = outerChanged = true; break; @@ -155,24 +157,22 @@ public: dataLogF("CFGSimplify: Branch to same successor merge on Block #%u to Block #%u.\n", blockIndex, targetBlockIndex); #endif + m_graph.dethread(); mergeBlocks(blockIndex, targetBlockIndex, NoBlock); } else { #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLogF("CFGSimplify: Branch->jump conversion to same successor on Block #%u to Block #%u.\n", blockIndex, targetBlockIndex); #endif - ASSERT(m_graph[block->last()].isTerminal()); - Node& branch = m_graph[block->last()]; - ASSERT(branch.isTerminal()); - ASSERT(branch.op() == Branch); - branch.setOpAndDefaultFlags(Phantom); - ASSERT(branch.refCount() == 1); + Node* branch = block->last(); + ASSERT(branch->isTerminal()); + ASSERT(branch->op() == Branch); + branch->convertToPhantom(); + ASSERT(branch->refCount() == 1); - Node jump(Jump, branch.codeOrigin, OpInfo(targetBlockIndex)); - jump.ref(); - NodeIndex jumpNodeIndex = m_graph.size(); - m_graph.append(jump); - block->append(jumpNodeIndex); + block->appendNode( + m_graph, SpecNone, Jump, branch->codeOrigin, + OpInfo(targetBlockIndex)); } innerChanged = outerChanged = true; break; @@ -239,7 +239,8 @@ public: } } - validate(m_graph); + if (Options::validateGraphAtEachPhase()) + validate(m_graph); } while (innerChanged); return outerChanged; @@ -253,109 +254,24 @@ private: ASSERT(block); ASSERT(!block->isReachable); - // 1) Remove references from other blocks to this block. - for (unsigned i = m_graph.numSuccessors(block); i--;) - fixPhis(blockIndex, m_graph.successor(block, i)); + for (unsigned phiIndex = block->phis.size(); phiIndex--;) + m_graph.m_allocator.free(block->phis[phiIndex]); + for (unsigned nodeIndex = block->size(); nodeIndex--;) + m_graph.m_allocator.free(block->at(nodeIndex)); - // 2) Kill the block m_graph.m_blocks[blockIndex].clear(); } - void keepOperandAlive(BasicBlock* block, CodeOrigin codeOrigin, int operand) + void keepOperandAlive(BasicBlock* block, BasicBlock* jettisonedBlock, CodeOrigin codeOrigin, int operand) { - NodeIndex nodeIndex = block->variablesAtTail.operand(operand); - if (nodeIndex == NoNode) + Node* livenessNode = jettisonedBlock->variablesAtHead.operand(operand); + if (!livenessNode) return; - if (m_graph[nodeIndex].variableAccessData()->isCaptured()) + if (livenessNode->variableAccessData()->isCaptured()) return; - if (m_graph[nodeIndex].op() == SetLocal) - nodeIndex = m_graph[nodeIndex].child1().index(); - Node& node = m_graph[nodeIndex]; - if (!node.shouldGenerate()) - return; - ASSERT(m_graph[nodeIndex].op() != SetLocal); - NodeIndex phantomNodeIndex = m_graph.size(); - Node phantom(Phantom, codeOrigin, nodeIndex); - m_graph.append(phantom); - m_graph.ref(phantomNodeIndex); - block->append(phantomNodeIndex); - } - - void fixPossibleGetLocal(BasicBlock* block, Edge& edge, bool changeRef) - { - Node& child = m_graph[edge]; - if (child.op() != GetLocal) - return; -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF(" Considering GetLocal at @%u, local r%d.\n", edge.index(), child.local()); -#endif - if (child.variableAccessData()->isCaptured()) { -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF(" It's captured.\n"); -#endif - return; - } - NodeIndex originalNodeIndex = block->variablesAtTail.operand(child.local()); -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF(" Dealing with original @%u.\n", originalNodeIndex); -#endif - ASSERT(originalNodeIndex != NoNode); - Node* originalNode = &m_graph[originalNodeIndex]; -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF(" Original has local r%d.\n", originalNode->local()); -#endif - ASSERT(child.local() == originalNode->local()); - // Possibilities: - // SetLocal -> the secondBlock is getting the value of something that is immediately - // available in the first block with a known NodeIndex. - // GetLocal -> the secondBlock is getting the value of something that the first - // block also gets. - // Phi -> the secondBlock is asking for keep-alive on an operand that the first block - // was also asking for keep-alive on. - // SetArgument -> the secondBlock is asking for keep-alive on an operand that the - // first block was keeping alive by virtue of the firstBlock being the root and - // the operand being an argument. - // Flush -> the secondBlock is asking for keep-alive on an operand that the first - // block was forcing to be alive, so the second block should refer child of - // the flush. - if (originalNode->op() == Flush) { - originalNodeIndex = originalNode->child1().index(); - originalNode = &m_graph[originalNodeIndex]; - } - switch (originalNode->op()) { - case SetLocal: { - if (changeRef) - ASSERT(originalNode->shouldGenerate()); -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF(" It's a SetLocal.\n"); -#endif - m_graph.changeIndex(edge, originalNode->child1().index(), changeRef); - break; - } - case GetLocal: { -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF(" It's a GetLocal.\n"); -#endif - if (originalNode->shouldGenerate()) - m_graph.changeIndex(edge, originalNodeIndex, changeRef); - // If we have a GetLocal that points to a child GetLocal that is dead, then - // we have no need to do anything: this original GetLocal is still valid. - break; - } - case Phi: - case SetArgument: { - if (changeRef) - ASSERT(originalNode->shouldGenerate()); -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF(" It's Phi/SetArgument.\n"); -#endif - // Keep the GetLocal! - break; - } - default: - ASSERT_NOT_REACHED(); - break; - } + block->appendNode( + m_graph, SpecNone, PhantomLocal, codeOrigin, + OpInfo(livenessNode->variableAccessData())); } void jettisonBlock(BlockIndex blockIndex, BlockIndex jettisonedBlockIndex, CodeOrigin boundaryCodeOrigin) @@ -364,46 +280,13 @@ private: BasicBlock* jettisonedBlock = m_graph.m_blocks[jettisonedBlockIndex].get(); for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfArguments(); ++i) - keepOperandAlive(block, boundaryCodeOrigin, argumentToOperand(i)); + keepOperandAlive(block, jettisonedBlock, boundaryCodeOrigin, argumentToOperand(i)); for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfLocals(); ++i) - keepOperandAlive(block, boundaryCodeOrigin, i); + keepOperandAlive(block, jettisonedBlock, boundaryCodeOrigin, i); fixJettisonedPredecessors(blockIndex, jettisonedBlockIndex); } - void fixPhis(BlockIndex sourceBlockIndex, BlockIndex destinationBlockIndex) - { - BasicBlock* sourceBlock = m_graph.m_blocks[sourceBlockIndex].get(); - BasicBlock* destinationBlock = m_graph.m_blocks[destinationBlockIndex].get(); - if (!destinationBlock) { - // If we're trying to kill off the source block and the destination block is already - // dead, then we're done! - return; - } - for (size_t i = 0; i < destinationBlock->phis.size(); ++i) { - NodeIndex phiNodeIndex = destinationBlock->phis[i]; - Node& phiNode = m_graph[phiNodeIndex]; - NodeIndex myNodeIndex = sourceBlock->variablesAtTail.operand(phiNode.local()); -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF("Considering removing reference from phi @%u to @%u on local r%d:", - phiNodeIndex, myNodeIndex, phiNode.local()); -#endif - if (myNodeIndex == NoNode) { - // This will happen if there is a phi in the destination that refers into - // the destination itself. - continue; - } - Node& myNode = m_graph[myNodeIndex]; - if (myNode.op() == GetLocal) - myNodeIndex = myNode.child1().index(); - for (unsigned j = 0; j < AdjacencyList::Size; ++j) - removePotentiallyDeadPhiReference(myNodeIndex, phiNode, j, sourceBlock->isReachable); -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF("\n"); -#endif - } - } - void fixJettisonedPredecessors(BlockIndex blockIndex, BlockIndex jettisonedBlockIndex) { #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) @@ -418,145 +301,6 @@ private: jettisonedBlock->m_predecessors.removeLast(); break; } - - fixPhis(blockIndex, jettisonedBlockIndex); - } - - void removePotentiallyDeadPhiReference(NodeIndex myNodeIndex, Node& phiNode, unsigned edgeIndex, bool changeRef) - { - if (phiNode.children.child(edgeIndex).indexUnchecked() != myNodeIndex) - return; -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF(" Removing reference at child %u.", edgeIndex); -#endif - if (changeRef && phiNode.shouldGenerate()) - m_graph.deref(myNodeIndex); - phiNode.children.removeEdgeFromBag(edgeIndex); - } - - struct OperandSubstitution { - OperandSubstitution() - : oldChild(NoNode) - , newChild(NoNode) - { - } - - explicit OperandSubstitution(NodeIndex oldChild) - : oldChild(oldChild) - , newChild(oldChild) - { - } - - OperandSubstitution(NodeIndex oldChild, NodeIndex newChild) - : oldChild(oldChild) - , newChild(newChild) - { - ASSERT((oldChild == NoNode) == (newChild == NoNode)); - } - - void dump(FILE* out) - { - if (oldChild == NoNode) - fprintf(out, "-"); - else - fprintf(out, "@%u -> @%u", oldChild, newChild); - } - - NodeIndex oldChild; - NodeIndex newChild; - }; - - NodeIndex skipGetLocal(NodeIndex nodeIndex) - { - if (nodeIndex == NoNode) - return NoNode; - Node& node = m_graph[nodeIndex]; - if (node.op() == GetLocal) - return node.child1().index(); - return nodeIndex; - } - - void recordPossibleIncomingReference( - BasicBlock* secondBlock, Operands<OperandSubstitution>& substitutions, int operand) - { - substitutions.operand(operand) = OperandSubstitution( - skipGetLocal(secondBlock->variablesAtTail.operand(operand))); - } - - void recordNewTarget(Operands<OperandSubstitution>& substitutions, int operand, NodeIndex nodeIndex) - { - ASSERT(m_graph[nodeIndex].op() == SetLocal - || m_graph[nodeIndex].op() == SetArgument - || m_graph[nodeIndex].op() == Flush - || m_graph[nodeIndex].op() == Phi); - substitutions.operand(operand).newChild = nodeIndex; - } - - void fixTailOperand( - BasicBlock* firstBlock, BasicBlock* secondBlock, int operand, - Operands<OperandSubstitution>& substitutions) - { - NodeIndex atSecondTail = secondBlock->variablesAtTail.operand(operand); - - if (atSecondTail == NoNode) { - // If the variable is dead at the end of the second block, then do nothing; essentially - // this means that we want the tail state to reflect whatever the first block did. - return; - } - - Node& secondNode = m_graph[atSecondTail]; - - switch (secondNode.op()) { - case SetLocal: - case Flush: { - // The second block did interesting things to the variables, so update the tail - // accordingly. - firstBlock->variablesAtTail.operand(operand) = atSecondTail; - break; - } - - case Phi: { - // Keep what was in the first block. - ASSERT(firstBlock->variablesAtTail.operand(operand) != NoNode); - recordNewTarget(substitutions, operand, skipGetLocal(firstBlock->variablesAtTail.operand(operand))); - break; - } - - case GetLocal: { - // If it's a GetLocal on a captured var, then definitely keep what was - // in the second block. In particular, it's possible that the first - // block doesn't even know about this variable. - if (secondNode.variableAccessData()->isCaptured()) { - firstBlock->variablesAtTail.operand(operand) = atSecondTail; - recordNewTarget(substitutions, operand, secondNode.child1().index()); - break; - } - - // It's possible that the second block had a GetLocal and the first block - // had a SetArgument or a Phi. Then update the tail. Otherwise keep what was in the - // first block. - NodeIndex atFirstTail = firstBlock->variablesAtTail.operand(operand); - ASSERT(atFirstTail != NoNode); - switch (m_graph[atFirstTail].op()) { - case SetArgument: - case Phi: - firstBlock->variablesAtTail.operand(operand) = atSecondTail; - recordNewTarget(substitutions, operand, secondNode.child1().index()); - break; - - default: - // Keep what was in the first block, and adjust the substitution to account for - // the fact that successors will refer to the child of the GetLocal. - ASSERT(firstBlock->variablesAtTail.operand(operand) != NoNode); - recordNewTarget(substitutions, operand, skipGetLocal(firstBlock->variablesAtTail.operand(operand))); - break; - } - break; - } - - default: - ASSERT_NOT_REACHED(); - } } void mergeBlocks( @@ -573,10 +317,10 @@ private: // 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(m_graph[firstBlock->last()].isTerminal()); - CodeOrigin boundaryCodeOrigin = m_graph[firstBlock->last()].codeOrigin; - m_graph[firstBlock->last()].setOpAndDefaultFlags(Phantom); - ASSERT(m_graph[firstBlock->last()].refCount() == 1); + ASSERT(firstBlock->last()->isTerminal()); + CodeOrigin boundaryCodeOrigin = firstBlock->last()->codeOrigin; + firstBlock->last()->convertToPhantom(); + ASSERT(firstBlock->last()->refCount() == 1); if (jettisonedBlockIndex != NoBlock) { BasicBlock* jettisonedBlock = m_graph.m_blocks[jettisonedBlockIndex].get(); @@ -586,101 +330,18 @@ private: // different path than secondBlock. for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfArguments(); ++i) - keepOperandAlive(firstBlock, boundaryCodeOrigin, argumentToOperand(i)); + keepOperandAlive(firstBlock, jettisonedBlock, boundaryCodeOrigin, argumentToOperand(i)); for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfLocals(); ++i) - keepOperandAlive(firstBlock, boundaryCodeOrigin, i); + keepOperandAlive(firstBlock, jettisonedBlock, boundaryCodeOrigin, i); } for (size_t i = 0; i < secondBlock->phis.size(); ++i) firstBlock->phis.append(secondBlock->phis[i]); - // Before we start changing the second block's graph, record what nodes would - // be referenced by successors of the second block. - Operands<OperandSubstitution> substitutions( - secondBlock->variablesAtTail.numberOfArguments(), - secondBlock->variablesAtTail.numberOfLocals()); - for (size_t i = 0; i < secondBlock->variablesAtTail.numberOfArguments(); ++i) - recordPossibleIncomingReference(secondBlock, substitutions, argumentToOperand(i)); - for (size_t i = 0; i < secondBlock->variablesAtTail.numberOfLocals(); ++i) - recordPossibleIncomingReference(secondBlock, substitutions, i); - - for (size_t i = 0; i < secondBlock->size(); ++i) { - NodeIndex nodeIndex = secondBlock->at(i); - Node& node = m_graph[nodeIndex]; - - bool childrenAlreadyFixed = false; - - switch (node.op()) { - case Phantom: { - if (!node.child1()) - break; - - ASSERT(node.shouldGenerate()); - Node& possibleLocalOp = m_graph[node.child1()]; - if (possibleLocalOp.op() != GetLocal - && possibleLocalOp.hasLocal() - && !possibleLocalOp.variableAccessData()->isCaptured()) { - NodeIndex setLocalIndex = - firstBlock->variablesAtTail.operand(possibleLocalOp.local()); - Node& setLocal = m_graph[setLocalIndex]; - if (setLocal.op() == SetLocal) { - m_graph.changeEdge(node.children.child1(), setLocal.child1()); - ASSERT(!node.child2()); - ASSERT(!node.child3()); - childrenAlreadyFixed = true; - } - } - break; - } - - case Flush: - case GetLocal: { - // A Flush could use a GetLocal, SetLocal, SetArgument, or a Phi. - // If it uses a GetLocal, it'll be taken care of below. If it uses a - // SetLocal or SetArgument, then it must be using a node from the - // same block. But if it uses a Phi, then we should redirect it to - // use whatever the first block advertised as a tail operand. - // Similarly for GetLocal; it could use any of those except for - // GetLocal. If it uses a Phi then it should be redirected to use a - // Phi from the tail operand. - if (m_graph[node.child1()].op() != Phi) - break; - - NodeIndex atFirstIndex = firstBlock->variablesAtTail.operand(node.local()); - m_graph.changeEdge(node.children.child1(), Edge(skipGetLocal(atFirstIndex)), node.shouldGenerate()); - childrenAlreadyFixed = true; - break; - } - - default: - break; - } - - if (!childrenAlreadyFixed) { - bool changeRef = node.shouldGenerate(); - - // If the child is a GetLocal, then we might like to fix it. - if (node.flags() & NodeHasVarArgs) { - for (unsigned childIdx = node.firstChild(); - childIdx < node.firstChild() + node.numChildren(); - ++childIdx) { - if (!!m_graph.m_varArgChildren[childIdx]) - fixPossibleGetLocal(firstBlock, m_graph.m_varArgChildren[childIdx], changeRef); - } - } else if (!!node.child1()) { - fixPossibleGetLocal(firstBlock, node.children.child1(), changeRef); - if (!!node.child2()) { - fixPossibleGetLocal(firstBlock, node.children.child2(), changeRef); - if (!!node.child3()) - fixPossibleGetLocal(firstBlock, node.children.child3(), changeRef); - } - } - } - - firstBlock->append(nodeIndex); - } + for (size_t i = 0; i < secondBlock->size(); ++i) + firstBlock->append(secondBlock->at(i)); - ASSERT(m_graph[firstBlock->last()].isTerminal()); + ASSERT(firstBlock->last()->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 @@ -700,39 +361,6 @@ private: if (jettisonedBlockIndex != NoBlock) fixJettisonedPredecessors(firstBlockIndex, jettisonedBlockIndex); - // Fix up the variables at tail. - for (size_t i = 0; i < secondBlock->variablesAtHead.numberOfArguments(); ++i) - fixTailOperand(firstBlock, secondBlock, argumentToOperand(i), substitutions); - for (size_t i = 0; i < secondBlock->variablesAtHead.numberOfLocals(); ++i) - fixTailOperand(firstBlock, secondBlock, i, substitutions); - - // Fix up the references from our new successors. - for (unsigned i = m_graph.numSuccessors(firstBlock); i--;) { - BasicBlock* successor = m_graph.m_blocks[m_graph.successor(firstBlock, i)].get(); - for (unsigned j = 0; j < successor->phis.size(); ++j) { - NodeIndex phiNodeIndex = successor->phis[j]; - Node& phiNode = m_graph[phiNodeIndex]; - bool changeRef = phiNode.shouldGenerate(); - OperandSubstitution substitution = substitutions.operand(phiNode.local()); -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLogF(" Performing operand substitution @%u -> @%u.\n", - substitution.oldChild, substitution.newChild); -#endif - if (!phiNode.child1()) - continue; - if (phiNode.child1().index() == substitution.oldChild) - m_graph.changeIndex(phiNode.children.child1(), substitution.newChild, changeRef); - if (!phiNode.child2()) - continue; - if (phiNode.child2().index() == substitution.oldChild) - m_graph.changeIndex(phiNode.children.child2(), substitution.newChild, changeRef); - if (!phiNode.child3()) - continue; - if (phiNode.child3().index() == substitution.oldChild) - m_graph.changeIndex(phiNode.children.child3(), substitution.newChild, changeRef); - } - } - firstBlock->valuesAtTail = secondBlock->valuesAtTail; firstBlock->cfaBranchDirection = secondBlock->cfaBranchDirection; |