# HG changeset patch # User Lukas Stadler # Date 1364391364 -3600 # Node ID 064e9f64fe5201e8ba948ca7953df8756bf9c294 # Parent 354d729ae588be8a2653828fbe381094f4ba54e5 fix for state duplication in ReentrantBlockIterator diff -r 354d729ae588 -r 064e9f64fe52 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Thu Mar 21 13:35:21 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Wed Mar 27 14:36:04 2013 +0100 @@ -24,7 +24,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.IterableNodeType; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.*; diff -r 354d729ae588 -r 064e9f64fe52 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Thu Mar 21 13:35:21 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java Wed Mar 27 14:36:04 2013 +0100 @@ -41,7 +41,7 @@ protected abstract StateT merge(MergeNode merge, List states); - protected abstract StateT afterSplit(FixedNode node, StateT oldState); + protected abstract StateT cloneState(StateT oldState); protected abstract List processLoop(Loop loop, StateT initialState); } @@ -56,25 +56,31 @@ LoopInfo info = new LoopInfo<>(); List predecessors = loop.header.getPredecessors(); for (int i = 1; i < predecessors.size(); i++) { - info.endStates.add(blockEndStates.get(predecessors.get(i).getEndNode())); + StateT endState = blockEndStates.get(predecessors.get(i).getEndNode()); + // make sure all end states are unique objects + info.endStates.add(closure.cloneState(endState)); } for (Block loopExit : loop.exits) { assert loopExit.getPredecessorCount() == 1; - StateT exitState = blockEndStates.get(loopExit.getFirstPredecessor().getEndNode()); + StateT exitState = blockEndStates.get(loopExit.getBeginNode()); assert exitState != null; - info.exitStates.add(exitState); + // make sure all exit states are unique objects + info.exitStates.add(closure.cloneState(exitState)); } return info; } public static IdentityHashMap apply(BlockIteratorClosure closure, Block start, StateT initialState, Set boundary) { Deque blockQueue = new ArrayDeque<>(); - IdentityHashMap blockEndStates = new IdentityHashMap<>(); + /* + * States are stored on EndNodes before merges, and on BeginNodes after ControlSplitNodes. + */ + IdentityHashMap states = new IdentityHashMap<>(); StateT state = initialState; Block current = start; - do { + while (true) { if (boundary == null || boundary.contains(current)) { closure.processBlock(current, state); @@ -86,7 +92,7 @@ if (current.isLoopEnd()) { // nothing to do... loop ends only lead to loop begins we've already // visited - blockEndStates.put(current.getEndNode(), state); + states.put(current.getEndNode(), state); } else { // recurse into the loop Loop loop = successor.getLoop(); @@ -98,14 +104,14 @@ int i = 0; assert loop.exits.size() == exitStates.size(); for (Block exit : loop.exits) { - blockEndStates.put(exit.getFirstPredecessor().getEndNode(), exitStates.get(i++)); + states.put(exit.getBeginNode(), exitStates.get(i++)); blockQueue.addFirst(exit); } } } else { if (successor.getBeginNode() instanceof LoopExitNode) { assert successor.getPredecessors().size() == 1; - blockEndStates.put(current.getEndNode(), state); + states.put(successor.getBeginNode(), state); current = successor; continue; } else { @@ -114,12 +120,12 @@ EndNode end = (EndNode) current.getEndNode(); // add the end node and see if the merge is ready for processing - assert !blockEndStates.containsKey(end); - blockEndStates.put(end, state); + assert !states.containsKey(end); + states.put(end, state); MergeNode merge = end.merge(); boolean endsVisited = true; for (EndNode forwardEnd : merge.forwardEnds()) { - if (!blockEndStates.containsKey(forwardEnd)) { + if (!states.containsKey(forwardEnd)) { endsVisited = false; break; } @@ -136,46 +142,34 @@ } } else { assert current.getSuccessors().size() > 1; - blockEndStates.put(current.getEndNode(), state); - for (Block block : current.getSuccessors()) { - blockQueue.addFirst(block); + for (int i = 0; i < current.getSuccessors().size(); i++) { + Block successor = current.getSuccessors().get(i); + blockQueue.addFirst(successor); + states.put(successor.getBeginNode(), i == 0 ? state : closure.cloneState(state)); } } } // get next queued block if (blockQueue.isEmpty()) { - current = null; + return states; } else { - int maxIterations = blockQueue.size(); - while (maxIterations-- > 0) { - current = blockQueue.removeFirst(); - if (current.getPredecessors().size() > 1) { - MergeNode merge = (MergeNode) current.getBeginNode(); - ArrayList states = new ArrayList<>(merge.forwardEndCount()); - for (int i = 0; i < merge.forwardEndCount(); i++) { - StateT other = blockEndStates.get(merge.forwardEndAt(i)); - assert other != null; - states.add(other); - } - state = closure.merge(merge, states); - if (state != null) { - break; - } else { - blockQueue.addLast(current); - current = null; - } - } else { - assert current.getPredecessors().size() == 1; - assert current.getBeginNode().predecessor() != null; - if (boundary == null || boundary.contains(current)) { - state = closure.afterSplit(current.getBeginNode(), blockEndStates.get(current.getBeginNode().predecessor())); - break; - } + current = blockQueue.removeFirst(); + if (current.getPredecessors().size() == 1) { + state = states.get(current.getBeginNode()); + } else { + assert current.getPredecessors().size() > 1; + MergeNode merge = (MergeNode) current.getBeginNode(); + ArrayList mergedStates = new ArrayList<>(merge.forwardEndCount()); + for (int i = 0; i < merge.forwardEndCount(); i++) { + StateT other = states.get(merge.forwardEndAt(i)); + assert other != null; + mergedStates.add(other); } + state = closure.merge(merge, mergedStates); } + assert state != null; } - } while (current != null); - return blockEndStates; + } } } diff -r 354d729ae588 -r 064e9f64fe52 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Thu Mar 21 13:35:21 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Wed Mar 27 14:36:04 2013 +0100 @@ -373,7 +373,7 @@ } @Override - protected BlockState afterSplit(FixedNode node, BlockState oldState) { + protected BlockState cloneState(BlockState oldState) { return oldState.cloneState(); }