changeset 8544:064e9f64fe52

fix for state duplication in ReentrantBlockIterator
author Lukas Stadler <lukas.stadler@jku.at>
date Wed, 27 Mar 2013 14:36:04 +0100
parents 354d729ae588
children e5da6c59d7c9
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java
diffstat 3 files changed, 38 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- 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.*;
--- 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<StateT> states);
 
-        protected abstract StateT afterSplit(FixedNode node, StateT oldState);
+        protected abstract StateT cloneState(StateT oldState);
 
         protected abstract List<StateT> processLoop(Loop loop, StateT initialState);
     }
@@ -56,25 +56,31 @@
         LoopInfo<StateT> info = new LoopInfo<>();
         List<Block> 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 <StateT> IdentityHashMap<FixedNode, StateT> apply(BlockIteratorClosure<StateT> closure, Block start, StateT initialState, Set<Block> boundary) {
         Deque<Block> blockQueue = new ArrayDeque<>();
-        IdentityHashMap<FixedNode, StateT> blockEndStates = new IdentityHashMap<>();
+        /*
+         * States are stored on EndNodes before merges, and on BeginNodes after ControlSplitNodes.
+         */
+        IdentityHashMap<FixedNode, StateT> 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<StateT> 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<StateT> 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;
+        }
     }
 }
--- 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();
     }