changeset 5487:9743ae819f73

Move virtual chain help methods from SuperBlock to GraphUtil Rename replaceAtPredecessors to replaceAtPredecessor
author Gilles Duboscq <duboscq@ssw.jku.at>
date Tue, 05 Jun 2012 17:38:48 +0200
parents 85986efe747e
children 21cab9000931
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformDataResolver.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/SuperBlock.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/SnippetIntrinsificationPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java
diffstat 15 files changed, 171 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformDataResolver.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformDataResolver.java	Tue Jun 05 17:38:48 2012 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
+import com.oracle.graal.nodes.util.*;
 
 
 
@@ -88,7 +89,7 @@
                             first = firstPhi;
                             merge.stateAfter().replaceFirstInput(phi, firstPhi); // fix the merge's state after (see SuperBlock.mergeExits)
                             if (phi.type() == PhiType.Virtual) {
-                                first = SuperBlock.mergeVirtualChain(graph, firstPhi, merge);
+                                first = GraphUtil.mergeVirtualChain(graph, firstPhi, merge);
                             }
                         }
                     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/SuperBlock.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/SuperBlock.java	Tue Jun 05 17:38:48 2012 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.nodes.virtual.*;
 
 public class SuperBlock {
     protected BeginNode entry;
@@ -165,7 +164,7 @@
             EndNode end = endsToMerge.get(0);
             assert end.usages().count() == 0;
             newExit = graph.add(new BeginNode());
-            end.replaceAtPredecessors(newExit);
+            end.replaceAtPredecessor(newExit);
             end.safeDelete();
         } else {
             assert endsToMerge.size() > 1;
@@ -224,7 +223,7 @@
                         assert vpn.type() == PhiType.Virtual;
                         ValueNode vof = GraphUtil.unProxify(vpn);
                         ValueNode newVof = GraphUtil.unProxify(newVpn);
-                        replaceWith = mergeVirtualChain(graph, vof, newVof, phi, earlyExit, newEarlyExit, merge);
+                        replaceWith = GraphUtil.mergeVirtualChain(graph, vof, newVof, phi, earlyExit, newEarlyExit, merge);
                     }
                 } else {
                     replaceWith = vpn.value();
@@ -239,130 +238,6 @@
         }
     }
 
-    private static ValueProxyNode findProxy(ValueNode value, BeginNode proxyPoint) {
-        for (ValueProxyNode vpn : proxyPoint.proxies()) {
-            ValueNode v = vpn;
-            while (v instanceof ValueProxyNode) {
-                v = ((ValueProxyNode) v).value();
-                if (v == value) {
-                    return vpn;
-                }
-            }
-        }
-        return null;
-    }
-
-    private static ValueNode mergeVirtualChain(
-                    StructuredGraph graph,
-                    ValueNode vof,
-                    ValueNode newVof,
-                    PhiNode vPhi,
-                    BeginNode earlyExit,
-                    BeginNode newEarlyExit,
-                    MergeNode merge) {
-        VirtualObjectNode vObject = virtualObject(vof);
-        assert virtualObject(newVof) == vObject;
-        ValueNode[] virtualState = virtualState(vof);
-        ValueNode[] newVirtualState = virtualState(newVof);
-        ValueNode chain = vPhi;
-        for (int i = 0; i < virtualState.length; i++) {
-            ValueNode value = virtualState[i];
-            ValueNode newValue = newVirtualState[i];
-            assert value.kind() == newValue.kind();
-            if (value != newValue) {
-                PhiNode valuePhi = graph.add(new PhiNode(value.kind(), merge));
-                ValueProxyNode inputProxy = findProxy(value, earlyExit);
-                if (inputProxy != null) {
-                    ValueProxyNode newInputProxy = findProxy(newValue, newEarlyExit);
-                    assert newInputProxy != null : "no proxy for " + newValue + " at " + newEarlyExit;
-                    valuePhi.addInput(inputProxy);
-                    valuePhi.addInput(newInputProxy);
-                } else {
-                    valuePhi.addInput(graph.unique(new ValueProxyNode(value, earlyExit, PhiType.Value)));
-                    valuePhi.addInput(newValue);
-                }
-                chain = graph.add(new VirtualObjectFieldNode(vObject, chain, valuePhi, i));
-            }
-        }
-        return chain;
-    }
-
-    public static ValueNode mergeVirtualChain(
-                    StructuredGraph graph,
-                    PhiNode vPhi,
-                    MergeNode merge) {
-        NodeInputList<ValueNode> virtuals = vPhi.values();
-        VirtualObjectNode vObject = virtualObject(GraphUtil.unProxify(virtuals.first()));
-        List<ValueNode[]> virtualStates = new ArrayList<>(virtuals.size());
-        for (ValueNode virtual : virtuals) {
-            virtualStates.add(virtualState(GraphUtil.unProxify(virtual)));
-        }
-        ValueNode chain = vPhi;
-        int stateLength = virtualStates.get(0).length;
-        for (int i = 0; i < stateLength; i++) {
-            ValueNode v = null;
-            boolean reconcile = false;
-            for (ValueNode[] state : virtualStates) {
-                if (v == null) {
-                    v = state[i];
-                } else if (v != state[i]) {
-                    reconcile = true;
-                    break;
-                }
-                assert v.kind() == state[i].kind();
-            }
-            if (reconcile) {
-                PhiNode valuePhi = graph.add(new PhiNode(v.kind(), merge));
-                for (ValueNode[] state : virtualStates) {
-                    valuePhi.addInput(state[i]);
-                }
-                chain = graph.add(new VirtualObjectFieldNode(vObject, chain, valuePhi, i));
-            }
-        }
-        return chain;
-    }
-
-    private static VirtualObjectNode virtualObject(ValueNode vof) {
-        assert vof instanceof VirtualObjectFieldNode || (vof instanceof PhiNode && ((PhiNode) vof).type() == PhiType.Virtual) : vof;
-        ValueNode currentField = vof;
-        do {
-            if (currentField instanceof VirtualObjectFieldNode) {
-               return ((VirtualObjectFieldNode) currentField).object();
-            } else {
-                assert currentField instanceof PhiNode && ((PhiNode) currentField).type() == PhiType.Virtual : currentField;
-                currentField = ((PhiNode) currentField).valueAt(0);
-            }
-        } while (currentField != null);
-        throw new GraalInternalError("Invalid virtual chain : cound not find virtual object from %s", vof);
-    }
-
-    private static ValueNode[] virtualState(ValueNode vof) {
-        VirtualObjectNode vObj = virtualObject(vof);
-        int fieldsCount = vObj.fieldsCount();
-        int dicovered = 0;
-        ValueNode[] state = new ValueNode[fieldsCount];
-        ValueNode currentField = vof;
-        do {
-            if (currentField instanceof VirtualObjectFieldNode) {
-                int index = ((VirtualObjectFieldNode) currentField).index();
-                if (state[index] == null) {
-                    dicovered++;
-                    state[index] = ((VirtualObjectFieldNode) currentField).input();
-                    if (dicovered >= fieldsCount) {
-                        break;
-                    }
-                }
-                currentField = ((VirtualObjectFieldNode) currentField).lastState();
-            } else if (currentField instanceof ValueProxyNode) {
-                currentField = ((ValueProxyNode) currentField).value();
-            } else {
-                assert currentField instanceof PhiNode && ((PhiNode) currentField).type() == PhiType.Virtual : currentField;
-                currentField = ((PhiNode) currentField).valueAt(0);
-            }
-        } while (currentField != null);
-        return state;
-    }
-
     private NodeBitMap computeNodes() {
         NodeBitMap nodes = entry.graph().createNodeBitMap();
         for (BeginNode b : blocks) {
@@ -432,7 +307,7 @@
     public void insertBefore(FixedNode fixed) {
         assert entry.predecessor() == null;
         assert exit.next() == null;
-        fixed.replaceAtPredecessors(entry);
+        fixed.replaceAtPredecessor(entry);
         exit.setNext(fixed);
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java	Tue Jun 05 17:38:48 2012 +0200
@@ -90,7 +90,7 @@
             FixedNode next = otherBegin.next();
             otherBegin.setNext(null);
             guard.setNext(next);
-            ifNode.replaceAtPredecessors(guard);
+            ifNode.replaceAtPredecessor(guard);
             GraphUtil.killCFG(ifNode);
         }
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/SnippetIntrinsificationPhase.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/SnippetIntrinsificationPhase.java	Tue Jun 05 17:38:48 2012 +0200
@@ -267,7 +267,7 @@
                 }
                 FixedNode next = checkCastNode.next();
                 checkCastNode.setNext(null);
-                checkCastNode.replaceAtPredecessors(next);
+                checkCastNode.replaceAtPredecessor(next);
                 GraphUtil.killCFG(checkCastNode);
             }
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java	Tue Jun 05 17:38:48 2012 +0200
@@ -806,7 +806,7 @@
         if (receiverNullCheck) {
             receiverNullCheck(invoke);
         }
-        invoke.node().replaceAtPredecessors(firstCFGNodeDuplicate);
+        invoke.node().replaceAtPredecessor(firstCFGNodeDuplicate);
 
         FrameState stateAtExceptionEdge = null;
         if (invoke instanceof InvokeWithExceptionNode) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Jun 05 17:38:48 2012 +0200
@@ -202,10 +202,10 @@
     }
 
     /**
-     * Updates the predecessor sets of the given nodes after a successor slot is changed from oldSuccessor to newSuccessor:
+     * Updates the predecessor of the given nodes after a successor slot is changed from oldSuccessor to newSuccessor:
      * removes this node from oldSuccessor's predecessors and adds this node to newSuccessor's predecessors.
      */
-    protected void updatePredecessors(Node oldSuccessor, Node newSuccessor) {
+    protected void updatePredecessor(Node oldSuccessor, Node newSuccessor) {
         assert assertTrue(usages != null, "usages == null while adding %s to %s", newSuccessor, this);
         if (oldSuccessor != newSuccessor) {
             if (oldSuccessor != null) {
@@ -228,7 +228,7 @@
             updateUsages(null, input);
         }
         for (Node successor : successors()) {
-            updatePredecessors(null, successor);
+            updatePredecessor(null, successor);
         }
     }
 
@@ -262,12 +262,12 @@
         usages.clear();
     }
 
-    public void replaceAtPredecessors(Node other) {
+    public void replaceAtPredecessor(Node other) {
         assert checkReplaceWith(other);
         if (predecessor != null) {
             boolean result = predecessor.getNodeClass().replaceFirstSuccessor(predecessor, this, other);
             assert assertTrue(result, "not found in successors, predecessor: %s", predecessor);
-            predecessor.updatePredecessors(this, other);
+            predecessor.updatePredecessor(this, other);
         }
     }
 
@@ -276,14 +276,14 @@
         if (other != null) {
             clearSuccessors();
             replaceAtUsages(other);
-            replaceAtPredecessors(other);
+            replaceAtPredecessor(other);
         }
         safeDelete();
     }
 
     public void replaceFirstSuccessor(Node oldSuccessor, Node newSuccessor) {
         if (getNodeClass().replaceFirstSuccessor(this, oldSuccessor, newSuccessor)) {
-            updatePredecessors(oldSuccessor, newSuccessor);
+            updatePredecessor(oldSuccessor, newSuccessor);
         }
     }
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Jun 05 17:38:48 2012 +0200
@@ -663,7 +663,7 @@
             if (pos.input) {
                 node.updateUsages(old, x);
             } else {
-                node.updatePredecessors(old, x);
+                node.updatePredecessor(old, x);
             }
         } else {
             NodeList<Node> list = getNodeList(node, offset);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java	Tue Jun 05 17:38:48 2012 +0200
@@ -43,7 +43,7 @@
 
     @Override
     protected void update(T oldNode, T newNode) {
-        self.updatePredecessors(oldNode, newNode);
+        self.updatePredecessor(oldNode, newNode);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Jun 05 17:38:48 2012 +0200
@@ -147,7 +147,7 @@
             if (node instanceof FixedWithNextNode) {
                 ((StructuredGraph) graph()).replaceFixedWithFixed(this, (FixedWithNextNode) node);
             } else if (node instanceof DeoptimizeNode) {
-                this.replaceAtPredecessors(node);
+                this.replaceAtPredecessor(node);
                 this.replaceAtUsages(null);
                 GraphUtil.killCFG(this);
                 return;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Jun 05 17:38:48 2012 +0200
@@ -185,7 +185,7 @@
             assert kind() == CiKind.Void && usages().isEmpty();
             ((StructuredGraph) graph()).removeSplit(this, NORMAL_EDGE);
         } else if (node instanceof DeoptimizeNode) {
-            this.replaceAtPredecessors(node);
+            this.replaceAtPredecessor(node);
             this.replaceAtUsages(null);
             GraphUtil.killCFG(this);
             return;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Tue Jun 05 17:38:48 2012 +0200
@@ -177,7 +177,7 @@
                     phi.addInput(newInput);
                 }
                 this.removeEnd(end);
-                end.replaceAtPredecessors(newEnd);
+                end.replaceAtPredecessor(newEnd);
                 end.safeDelete();
                 tool.addToWorkList(newEnd.predecessor()); // ?
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java	Tue Jun 05 17:38:48 2012 +0200
@@ -35,7 +35,7 @@
     }
 
     public void setScheduledNext(ScheduledNode x) {
-        updatePredecessors(scheduledNext, x);
+        updatePredecessor(scheduledNext, x);
         scheduledNext = x;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Jun 05 17:38:48 2012 +0200
@@ -201,7 +201,7 @@
         assert node.usages().isEmpty() : node + " " + node.usages();
         FixedNode next = node.next();
         node.setNext(null);
-        node.replaceAtPredecessors(next);
+        node.replaceAtPredecessor(next);
         node.safeDelete();
     }
 
@@ -228,7 +228,7 @@
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
         FixedNode next = node.next();
         node.setNext(null);
-        node.replaceAtPredecessors(next);
+        node.replaceAtPredecessor(next);
         node.replaceAtUsages(replacement);
         node.safeDelete();
     }
@@ -241,7 +241,7 @@
         for (int i = 0; i < node.blockSuccessorCount(); i++) {
             node.setBlockSuccessor(i, null);
         }
-        node.replaceAtPredecessors(begin);
+        node.replaceAtPredecessor(begin);
         node.safeDelete();
     }
 
@@ -258,7 +258,7 @@
             }
         }
         if (begin.isAlive()) {
-            node.replaceAtPredecessors(begin);
+            node.replaceAtPredecessor(begin);
             node.safeDelete();
         } else {
             assert node.isDeleted();
@@ -293,7 +293,7 @@
         for (int i = 0; i < node.blockSuccessorCount(); i++) {
             node.setBlockSuccessor(i, null);
         }
-        node.replaceAtPredecessors(begin);
+        node.replaceAtPredecessor(begin);
         node.replaceAtUsages(replacement);
         node.safeDelete();
     }
@@ -353,7 +353,7 @@
             stateAfter.safeDelete();
         }
         if (sux == null) {
-            singleEnd.replaceAtPredecessors(null);
+            singleEnd.replaceAtPredecessor(null);
             singleEnd.safeDelete();
         } else {
             singleEnd.replaceAndDelete(sux);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Tue Jun 05 17:38:48 2012 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.iterators.NodePredicates.PositiveTypePredicate;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.virtual.*;
 
@@ -95,7 +96,7 @@
 
             // null out remaining usages
             node.replaceAtUsages(null);
-            node.replaceAtPredecessors(null);
+            node.replaceAtPredecessor(null);
             killWithUnusedFloatingInputs(node);
 
             for (Node usage : usagesSnapshot) {
@@ -186,4 +187,144 @@
         }
         return v;
     }
+
+    private static ValueProxyNode findProxy(ValueNode value, BeginNode proxyPoint) {
+        for (ValueProxyNode vpn : proxyPoint.proxies()) {
+            ValueNode v = vpn;
+            while (v instanceof ValueProxyNode) {
+                v = ((ValueProxyNode) v).value();
+                if (v == value) {
+                    return vpn;
+                }
+            }
+        }
+        return null;
+    }
+
+    public static ValueNode mergeVirtualChain(
+                    StructuredGraph graph,
+                    ValueNode vof,
+                    ValueNode newVof,
+                    PhiNode vPhi,
+                    BeginNode earlyExit,
+                    BeginNode newEarlyExit,
+                    MergeNode merge) {
+        VirtualObjectNode vObject = virtualObject(vof);
+        assert virtualObject(newVof) == vObject;
+        ValueNode[] virtualState = virtualState(vof);
+        ValueNode[] newVirtualState = virtualState(newVof);
+        ValueNode chain = vPhi;
+        for (int i = 0; i < virtualState.length; i++) {
+            ValueNode value = virtualState[i];
+            ValueNode newValue = newVirtualState[i];
+            assert value.kind() == newValue.kind();
+            if (value != newValue) {
+                PhiNode valuePhi = graph.add(new PhiNode(value.kind(), merge));
+                ValueProxyNode inputProxy = findProxy(value, earlyExit);
+                if (inputProxy != null) {
+                    ValueProxyNode newInputProxy = findProxy(newValue, newEarlyExit);
+                    assert newInputProxy != null : "no proxy for " + newValue + " at " + newEarlyExit;
+                    valuePhi.addInput(inputProxy);
+                    valuePhi.addInput(newInputProxy);
+                } else {
+                    valuePhi.addInput(graph.unique(new ValueProxyNode(value, earlyExit, PhiType.Value)));
+                    valuePhi.addInput(newValue);
+                }
+                chain = graph.add(new VirtualObjectFieldNode(vObject, chain, valuePhi, i));
+            }
+        }
+        return chain;
+    }
+
+    public static ValueNode mergeVirtualChain(
+                    StructuredGraph graph,
+                    PhiNode vPhi,
+                    MergeNode merge) {
+        NodeInputList<ValueNode> virtuals = vPhi.values();
+        VirtualObjectNode vObject = virtualObject(unProxify(virtuals.first()));
+        List<ValueNode[]> virtualStates = new ArrayList<>(virtuals.size());
+        for (ValueNode virtual : virtuals) {
+            virtualStates.add(virtualState(unProxify(virtual)));
+        }
+        ValueNode chain = vPhi;
+        int stateLength = virtualStates.get(0).length;
+        for (int i = 0; i < stateLength; i++) {
+            ValueNode v = null;
+            boolean reconcile = false;
+            for (ValueNode[] state : virtualStates) {
+                if (v == null) {
+                    v = state[i];
+                } else if (v != state[i]) {
+                    reconcile = true;
+                    break;
+                }
+                assert v.kind() == state[i].kind();
+            }
+            if (reconcile) {
+                PhiNode valuePhi = graph.add(new PhiNode(v.kind(), merge));
+                for (ValueNode[] state : virtualStates) {
+                    valuePhi.addInput(state[i]);
+                }
+                chain = graph.add(new VirtualObjectFieldNode(vObject, chain, valuePhi, i));
+            }
+        }
+        return chain;
+    }
+
+    /**
+     * Returns the VirtualObjectNode associated with the virtual chain of the provided virtual node.
+     * @param vof a virtual ValueNode (a VirtualObjectFieldNode or a Virtual Phi)
+     * @return the VirtualObjectNode associated with the virtual chain of the provided virtual node.
+     */
+    public static VirtualObjectNode virtualObject(ValueNode vof) {
+        assert vof instanceof VirtualObjectFieldNode || (vof instanceof PhiNode && ((PhiNode) vof).type() == PhiType.Virtual) : vof;
+        ValueNode currentField = vof;
+        do {
+            if (currentField instanceof VirtualObjectFieldNode) {
+               return ((VirtualObjectFieldNode) currentField).object();
+            } else {
+                assert currentField instanceof PhiNode && ((PhiNode) currentField).type() == PhiType.Virtual : currentField;
+                currentField = ((PhiNode) currentField).valueAt(0);
+            }
+        } while (currentField != null);
+        throw new GraalInternalError("Invalid virtual chain : cound not find virtual object from %s", vof);
+    }
+
+    /**
+     * Builds the state of the virtual object at the provided point into a virtual chain.
+     * @param vof a virtual ValueNode (a VirtualObjectFieldNode or a Virtual Phi)
+     * @return the state of the virtual object at the provided point into a virtual chain.
+     */
+    public static ValueNode[] virtualState(ValueNode vof) {
+        return virtualState(vof, virtualObject(vof));
+    }
+
+    /**
+     * Builds the state of the virtual object at the provided point into a virtual chain.
+     * @param vof a virtual ValueNode (a VirtualObjectFieldNode or a Virtual Phi)
+     * @param vObj the virtual object
+     * @return the state of the virtual object at the provided point into a virtual chain.
+     */
+    public static ValueNode[] virtualState(ValueNode vof, VirtualObjectNode vObj) {
+        int fieldsCount = vObj.fieldsCount();
+        int dicovered = 0;
+        ValueNode[] state = new ValueNode[fieldsCount];
+        ValueNode currentField = vof;
+        do {
+            if (currentField instanceof VirtualObjectFieldNode) {
+                int index = ((VirtualObjectFieldNode) currentField).index();
+                if (state[index] == null) {
+                    dicovered++;
+                    state[index] = ((VirtualObjectFieldNode) currentField).input();
+                }
+                currentField = ((VirtualObjectFieldNode) currentField).lastState();
+            } else if (currentField instanceof ValueProxyNode) {
+                currentField = ((ValueProxyNode) currentField).value();
+            } else {
+                assert currentField instanceof PhiNode && ((PhiNode) currentField).type() == PhiType.Virtual : currentField;
+                currentField = ((PhiNode) currentField).valueAt(0);
+            }
+        } while (currentField != null && dicovered < fieldsCount);
+        return state;
+    }
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Mon Jun 04 16:15:56 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Tue Jun 05 17:38:48 2012 +0200
@@ -144,7 +144,7 @@
 
                             FixedNode explodeLoopNext = explodeLoop.next();
                             explodeLoop.clearSuccessors();
-                            explodeLoop.replaceAtPredecessors(explodeLoopNext);
+                            explodeLoop.replaceAtPredecessor(explodeLoopNext);
                             explodeLoop.replaceAtUsages(null);
                             GraphUtil.killCFG(explodeLoop);
                             break;
@@ -296,7 +296,7 @@
 
         // Re-wire the control flow graph around the replacee
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
-        anchor.replaceAtPredecessors(firstCFGNodeDuplicate);
+        anchor.replaceAtPredecessor(firstCFGNodeDuplicate);
         FixedNode next = anchor.next();
         anchor.setNext(null);