changeset 7257:b1ebd583be14

Remove @Successor private final NodeSuccessorList<BeginNode> blockSuccessors from ControlSplitNode Use normal successor fields in IfNode and InvokeWithException MergeableState.afterSplit(FixedNode) is now MergeableState.afterSplit(BeginNode)
author Gilles Duboscq <duboscq@ssw.jku.at>
date Tue, 18 Dec 2012 11:27:12 +0100
parents 9e155cd2bb2f
children 9bee93f61522
files graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertUnreachedToGuardPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java
diffstat 21 files changed, 157 insertions(+), 172 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Tue Dec 18 11:27:12 2012 +0100
@@ -63,7 +63,7 @@
         int inFalseBranch = loop.nodesInLoopFrom(ifNode.falseSuccessor(), postDom).cardinality();
         int loopTotal = loop.size();
         int netDiff = loopTotal - (inTrueBranch + inFalseBranch);
-        double uncertainty = (0.5 - Math.abs(ifNode.probability(IfNode.TRUE_EDGE) - 0.5)) * 2;
+        double uncertainty = (0.5 - Math.abs(ifNode.probability(ifNode.trueSuccessor()) - 0.5)) * 2;
         int maxDiff = GraalOptions.LoopUnswitchMaxIncrease + (int) (GraalOptions.LoopUnswitchUncertaintyBoost * loop.loopBegin().loopFrequency() * uncertainty);
         Debug.log("shouldUnswitch(%s, %s) : delta=%d, max=%d, %.2f%% inside of if", loop, ifNode, netDiff, maxDiff, (double) (inTrueBranch + inFalseBranch) / loopTotal * 100);
         return netDiff <= maxDiff;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Tue Dec 18 11:27:12 2012 +0100
@@ -96,7 +96,7 @@
         StructuredGraph graph = (StructuredGraph) ifNode.graph();
         BeginNode tempBegin = graph.add(new BeginNode());
         originalLoop.entryPoint().replaceAtPredecessor(tempBegin);
-        double takenProbability = ifNode.probability(ifNode.blockSuccessorIndex(ifNode.trueSuccessor()));
+        double takenProbability = ifNode.probability(ifNode.trueSuccessor());
         IfNode newIf = graph.add(new IfNode(ifNode.condition(), duplicateLoop.entryPoint(), originalLoop.entryPoint(), takenProbability, ifNode.leafGraphId()));
         tempBegin.setNext(newIf);
         ifNode.setCondition(graph.unique(ConstantNode.forBoolean(false, graph)));
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Tue Dec 18 11:27:12 2012 +0100
@@ -53,7 +53,7 @@
                         if (LoopPolicies.shouldTryUnswitch(loop)) {
                             IfNode ifNode = LoopTransformations.findUnswitchableIf(loop);
                             if (ifNode != null && LoopPolicies.shouldUnswitch(loop, ifNode)) {
-                                Debug.log("Unswitching %s at %s [%f - %f]", loop, ifNode, ifNode.probability(0), ifNode.probability(1));
+                                Debug.log("Unswitching %s at %s [%f - %f]", loop, ifNode, ifNode.probability(ifNode.trueSuccessor()), ifNode.probability(ifNode.falseSuccessor()));
                                 LoopTransformations.unswitch(loop, ifNode);
                                 UNSWITCHED.increment();
                                 Debug.dump(graph, "After unswitch %s", loop);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java	Tue Dec 18 11:27:12 2012 +0100
@@ -22,62 +22,16 @@
  */
 package com.oracle.graal.nodes;
 
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code ControlSplitNode} is a base class for all instructions that split the control flow (ie. have more than one successor).
  */
 public abstract class ControlSplitNode extends FixedNode {
-    @Successor private final NodeSuccessorList<BeginNode> blockSuccessors;
-    protected double[] branchProbability;
 
-    public BeginNode blockSuccessor(int index) {
-        return blockSuccessors.get(index);
-    }
-
-    public void setBlockSuccessor(int index, BeginNode x) {
-        blockSuccessors.set(index, x);
-    }
-
-    public int blockSuccessorCount() {
-        return blockSuccessors.size();
-    }
-
-    public ControlSplitNode(Stamp stamp, BeginNode[] blockSuccessors, double[] branchProbability) {
+    public ControlSplitNode(Stamp stamp) {
         super(stamp);
-        assert branchProbability.length == blockSuccessors.length;
-        this.blockSuccessors = new NodeSuccessorList<>(this, blockSuccessors);
-        this.branchProbability = branchProbability;
     }
 
-    public double probability(int successorIndex) {
-        return branchProbability[successorIndex];
-    }
-
-    public void setProbability(int successorIndex, double x) {
-        branchProbability[successorIndex] = x;
-    }
-
-    public NodeIterable<BeginNode> blockSuccessors() {
-        return blockSuccessors;
-    }
-
-    public int blockSuccessorIndex(BeginNode successor) {
-        int idx = blockSuccessors.indexOf(successor);
-        if (idx < 0) {
-            throw new IllegalArgumentException();
-        }
-        return idx;
-    }
-
-    @Override
-    public ControlSplitNode clone(Graph into) {
-        ControlSplitNode csn = (ControlSplitNode) super.clone(into);
-        csn.branchProbability = Arrays.copyOf(branchProbability, branchProbability.length);
-        return csn;
-    }
+    public abstract double probability(BeginNode successor);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Dec 18 11:27:12 2012 +0100
@@ -38,11 +38,11 @@
  * comparison.
  */
 public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, Negatable {
-    public static final int TRUE_EDGE = 0;
-    public static final int FALSE_EDGE = 1;
     private final long leafGraphId;
-
+    @Successor private BeginNode trueSuccessor;
+    @Successor private BeginNode falseSuccessor;
     @Input private BooleanNode condition;
+    private double takenProbability;
 
     public BooleanNode condition() {
         return condition;
@@ -54,9 +54,17 @@
     }
 
     public IfNode(BooleanNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double takenProbability, long leafGraphId) {
-        super(StampFactory.forVoid(), new BeginNode[] {BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor)}, new double[] {takenProbability, 1 - takenProbability});
+        this(condition, BeginNode.begin(trueSuccessor), BeginNode.begin(falseSuccessor), takenProbability, leafGraphId);
+    }
+
+    public IfNode(BooleanNode condition, BeginNode trueSuccessor, BeginNode falseSuccessor, double takenProbability, long leafGraphId) {
+        super(StampFactory.forVoid());
         this.condition = condition;
+        this.falseSuccessor = falseSuccessor;
+        this.takenProbability = takenProbability;
         this.leafGraphId = leafGraphId;
+        this.trueSuccessor = trueSuccessor;
+
     }
 
     public long leafGraphId() {
@@ -69,7 +77,7 @@
      * @return the true successor
      */
     public BeginNode trueSuccessor() {
-        return blockSuccessor(0);
+        return trueSuccessor;
     }
 
     /**
@@ -78,15 +86,17 @@
      * @return the false successor
      */
     public BeginNode falseSuccessor() {
-        return blockSuccessor(1);
+        return falseSuccessor;
     }
 
     public void setTrueSuccessor(BeginNode node) {
-        setBlockSuccessor(0, node);
+        updatePredecessor(trueSuccessor, node);
+        trueSuccessor = node;
     }
 
     public void setFalseSuccessor(BeginNode node) {
-        setBlockSuccessor(1, node);
+        updatePredecessor(falseSuccessor, node);
+        falseSuccessor = node;
     }
 
     /**
@@ -96,7 +106,24 @@
      * @return the corresponding successor
      */
     public BeginNode successor(boolean istrue) {
-        return blockSuccessor(istrue ? 0 : 1);
+        return istrue ? trueSuccessor : falseSuccessor;
+    }
+
+    @Override
+    public Negatable negate() {
+        BeginNode trueSucc = trueSuccessor();
+        BeginNode falseSucc = falseSuccessor();
+        setTrueSuccessor(null);
+        setFalseSuccessor(null);
+        setTrueSuccessor(falseSucc);
+        setFalseSuccessor(trueSucc);
+        takenProbability = 1 - takenProbability;
+        return this;
+    }
+
+    @Override
+    public double probability(BeginNode successor) {
+        return successor == trueSuccessor ? takenProbability : 1 - takenProbability;
     }
 
     @Override
@@ -119,11 +146,11 @@
             if (c.asConstant().asBoolean()) {
                 tool.deleteBranch(falseSuccessor());
                 tool.addToWorkList(trueSuccessor());
-                ((StructuredGraph) graph()).removeSplit(this, TRUE_EDGE);
+                ((StructuredGraph) graph()).removeSplit(this, trueSuccessor());
             } else {
                 tool.deleteBranch(trueSuccessor());
                 tool.addToWorkList(falseSuccessor());
-                ((StructuredGraph) graph()).removeSplit(this, FALSE_EDGE);
+                ((StructuredGraph) graph()).removeSplit(this, falseSuccessor());
             }
         } else if (trueSuccessor().guards().isEmpty() && falseSuccessor().guards().isEmpty()) {
             if (removeOrMaterializeIf(tool)) {
@@ -154,7 +181,7 @@
                     PhiNode singlePhi = phis.next();
                     if (!phis.hasNext()) {
                         // one phi at the merge of an otherwise empty if construct: try to convert into a MaterializeNode
-                        boolean inverted = trueEnd == merge.forwardEndAt(FALSE_EDGE);
+                        boolean inverted = trueEnd == merge.forwardEndAt(1);
                         ValueNode trueValue = singlePhi.valueAt(inverted ? 1 : 0);
                         ValueNode falseValue = singlePhi.valueAt(inverted ? 0 : 1);
                         if (trueValue.kind() != falseValue.kind()) {
@@ -276,8 +303,8 @@
         List<EndNode> trueEnds = new ArrayList<>(mergePredecessors.size());
         Map<EndNode, ValueNode> phiValues = new HashMap<>(mergePredecessors.size());
 
-        BeginNode falseSuccessor = falseSuccessor();
-        BeginNode trueSuccessor = trueSuccessor();
+        BeginNode oldFalseSuccessor = falseSuccessor();
+        BeginNode oldTrueSuccessor = trueSuccessor();
 
         setFalseSuccessor(null);
         setTrueSuccessor(null);
@@ -294,8 +321,8 @@
         }
         assert !ends.hasNext();
 
-        connectEnds(falseEnds, phiValues, falseSuccessor, merge, tool);
-        connectEnds(trueEnds, phiValues, trueSuccessor, merge, tool);
+        connectEnds(falseEnds, phiValues, oldFalseSuccessor, merge, tool);
+        connectEnds(trueEnds, phiValues, oldTrueSuccessor, merge, tool);
 
         GraphUtil.killCFG(merge);
 
@@ -382,20 +409,20 @@
     }
 
     private void removeEmptyIf(SimplifierTool tool) {
-        BeginNode trueSuccessor = trueSuccessor();
-        BeginNode falseSuccessor = falseSuccessor();
-        assert trueSuccessor.next() instanceof EndNode && falseSuccessor.next() instanceof EndNode;
+        BeginNode originalTrueSuccessor = trueSuccessor();
+        BeginNode originalFalseSuccessor = falseSuccessor();
+        assert originalTrueSuccessor.next() instanceof EndNode && originalFalseSuccessor.next() instanceof EndNode;
 
-        EndNode trueEnd = (EndNode) trueSuccessor.next();
-        EndNode falseEnd = (EndNode) falseSuccessor.next();
+        EndNode trueEnd = (EndNode) originalTrueSuccessor.next();
+        EndNode falseEnd = (EndNode) originalFalseSuccessor.next();
         assert trueEnd.merge() == falseEnd.merge();
 
         FixedWithNextNode pred = (FixedWithNextNode) predecessor();
         MergeNode merge = trueEnd.merge();
         merge.prepareDelete(pred);
         assert merge.usages().isEmpty();
-        trueSuccessor.prepareDelete();
-        falseSuccessor.prepareDelete();
+        originalTrueSuccessor.prepareDelete();
+        originalFalseSuccessor.prepareDelete();
 
         FixedNode next = merge.next();
         merge.setNext(null);
@@ -403,25 +430,11 @@
         setFalseSuccessor(null);
         pred.setNext(next);
         safeDelete();
-        trueSuccessor.safeDelete();
-        falseSuccessor.safeDelete();
+        originalTrueSuccessor.safeDelete();
+        originalFalseSuccessor.safeDelete();
         merge.safeDelete();
         trueEnd.safeDelete();
         falseEnd.safeDelete();
         tool.addToWorkList(next);
     }
-
-    @Override
-    public Negatable negate() {
-        BeginNode trueSucc = trueSuccessor();
-        BeginNode falseSucc = falseSuccessor();
-        setTrueSuccessor(null);
-        setFalseSuccessor(null);
-        setTrueSuccessor(falseSucc);
-        setFalseSuccessor(trueSucc);
-        double prop = branchProbability[TRUE_EDGE];
-        branchProbability[TRUE_EDGE] = branchProbability[FALSE_EDGE];
-        branchProbability[FALSE_EDGE] = prop;
-        return this;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Dec 18 11:27:12 2012 +0100
@@ -33,9 +33,8 @@
 
 @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}")
 public class InvokeWithExceptionNode extends ControlSplitNode implements Node.IterableNodeType, Invoke, MemoryCheckpoint, LIRLowerable {
-    public static final int NORMAL_EDGE = 0;
-    public static final int EXCEPTION_EDGE = 1;
-
+    @Successor private BeginNode next;
+    @Successor private DispatchBeginNode exceptionEdge;
     @Input private final CallTargetNode callTarget;
     @Input private FrameState stateAfter;
     private final int bci;
@@ -44,7 +43,8 @@
     private final long leafGraphId;
 
     public InvokeWithExceptionNode(CallTargetNode callTarget, DispatchBeginNode exceptionEdge, int bci, long leafGraphId) {
-        super(callTarget.returnStamp(), new BeginNode[]{null, exceptionEdge}, new double[]{1.0, 0.0});
+        super(callTarget.returnStamp());
+        this.exceptionEdge = exceptionEdge;
         this.bci = bci;
         this.callTarget = callTarget;
         this.leafGraphId = leafGraphId;
@@ -53,19 +53,21 @@
     }
 
     public DispatchBeginNode exceptionEdge() {
-        return (DispatchBeginNode) blockSuccessor(EXCEPTION_EDGE);
+        return exceptionEdge;
     }
 
-    public void setExceptionEdge(BeginNode x) {
-        setBlockSuccessor(EXCEPTION_EDGE, x);
+    public void setExceptionEdge(DispatchBeginNode x) {
+        updatePredecessor(exceptionEdge, x);
+        exceptionEdge = x;
     }
 
     public BeginNode next() {
-        return blockSuccessor(NORMAL_EDGE);
+        return next;
     }
 
     public void setNext(BeginNode x) {
-        setBlockSuccessor(NORMAL_EDGE, x);
+        updatePredecessor(next, x);
+        next = x;
     }
 
     public CallTargetNode callTarget() {
@@ -170,9 +172,9 @@
     }
 
     public void killExceptionEdge() {
-        BeginNode exceptionEdge = exceptionEdge();
+        BeginNode edge = exceptionEdge();
         setExceptionEdge(null);
-        GraphUtil.killCFG(exceptionEdge);
+        GraphUtil.killCFG(edge);
     }
 
     @Override
@@ -187,18 +189,24 @@
         }
         if (node == null) {
             assert kind() == Kind.Void && usages().isEmpty();
-            ((StructuredGraph) graph()).removeSplit(this, NORMAL_EDGE);
+            ((StructuredGraph) graph()).removeSplit(this, next());
         } else if (node instanceof DeoptimizeNode) {
             this.replaceAtPredecessor(node);
             this.replaceAtUsages(null);
             GraphUtil.killCFG(this);
             return;
         } else {
-            ((StructuredGraph) graph()).replaceSplit(this, node, NORMAL_EDGE);
+            ((StructuredGraph) graph()).replaceSplit(this, node, next());
         }
         call.safeDelete();
         if (state.usages().isEmpty()) {
             state.safeDelete();
         }
     }
+
+    private static final double EXCEPTION_PROBA = 1e-5;
+    @Override
+    public double probability(BeginNode successor) {
+        return successor == next ? 1 - EXCEPTION_PROBA : EXCEPTION_PROBA;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Tue Dec 18 11:27:12 2012 +0100
@@ -241,39 +241,34 @@
         node.safeDelete();
     }
 
-    public void removeSplit(ControlSplitNode node, int survivingSuccessor) {
+    public void removeSplit(ControlSplitNode node, BeginNode survivingSuccessor) {
         assert node != null;
         assert node.usages().isEmpty();
-        assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
-        BeginNode begin = node.blockSuccessor(survivingSuccessor);
-        for (int i = 0; i < node.blockSuccessorCount(); i++) {
-            node.setBlockSuccessor(i, null);
-        }
-        node.replaceAtPredecessor(begin);
+        assert survivingSuccessor != null;
+        node.clearSuccessors();
+        node.replaceAtPredecessor(survivingSuccessor);
         node.safeDelete();
     }
 
-    public void removeSplitPropagate(ControlSplitNode node, int survivingSuccessor) {
+    public void removeSplitPropagate(ControlSplitNode node, BeginNode survivingSuccessor) {
         assert node != null;
         assert node.usages().isEmpty();
-        assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
-        BeginNode begin = node.blockSuccessor(survivingSuccessor);
-        for (int i = 0; i < node.blockSuccessorCount(); i++) {
-            BeginNode successor = node.blockSuccessor(i);
-            node.setBlockSuccessor(i, null);
-            if (successor != null && successor != begin && successor.isAlive()) {
-                GraphUtil.killCFG(successor);
+        assert survivingSuccessor != null;
+        for (Node successor : node.successors().snapshot()) {
+            successor.replaceAtPredecessor(null);
+            if (successor != null && successor != survivingSuccessor && successor.isAlive()) {
+                GraphUtil.killCFG((BeginNode) successor);
             }
         }
-        if (begin.isAlive()) {
-            node.replaceAtPredecessor(begin);
+        if (survivingSuccessor.isAlive()) {
+            node.replaceAtPredecessor(survivingSuccessor);
             node.safeDelete();
         } else {
-            assert node.isDeleted() : node + " " + begin;
+            assert node.isDeleted() : node + " " + survivingSuccessor;
         }
     }
 
-    public void replaceSplit(ControlSplitNode node, Node replacement, int survivingSuccessor) {
+    public void replaceSplit(ControlSplitNode node, Node replacement, BeginNode survivingSuccessor) {
         if (replacement instanceof FixedWithNextNode) {
             replaceSplitWithFixed(node, (FixedWithNextNode) replacement, survivingSuccessor);
         } else {
@@ -283,25 +278,19 @@
         }
     }
 
-    public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, int survivingSuccessor) {
+    public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, BeginNode survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
-        assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
-        BeginNode begin = node.blockSuccessor(survivingSuccessor);
-        for (int i = 0; i < node.blockSuccessorCount(); i++) {
-            node.setBlockSuccessor(i, null);
-        }
-        replacement.setNext(begin);
+        assert survivingSuccessor != null;
+        node.clearSuccessors();
+        replacement.setNext(survivingSuccessor);
         node.replaceAndDelete(replacement);
     }
 
-    public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, int survivingSuccessor) {
+    public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, BeginNode survivingSuccessor) {
         assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
-        assert survivingSuccessor >= 0 && survivingSuccessor < node.blockSuccessorCount() : "invalid surviving successor " + survivingSuccessor + " for " + node;
-        BeginNode begin = node.blockSuccessor(survivingSuccessor);
-        for (int i = 0; i < node.blockSuccessorCount(); i++) {
-            node.setBlockSuccessor(i, null);
-        }
-        node.replaceAtPredecessor(begin);
+        assert survivingSuccessor != null;
+        node.clearSuccessors();
+        node.replaceAtPredecessor(survivingSuccessor);
         node.replaceAtUsages(replacement);
         node.safeDelete();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Tue Dec 18 11:27:12 2012 +0100
@@ -93,7 +93,7 @@
     public void simplify(SimplifierTool tool) {
         if (blockSuccessorCount() == 1) {
             tool.addToWorkList(defaultSuccessor());
-            ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessorIndex());
+            ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessor());
         } else if (value() instanceof ConstantNode) {
             int constant = value().asConstant().asInt();
 
@@ -109,7 +109,7 @@
                 }
             }
             tool.addToWorkList(blockSuccessor(survivingEdge));
-            ((StructuredGraph) graph()).removeSplitPropagate(this, survivingEdge);
+            ((StructuredGraph) graph()).removeSplit(this, blockSuccessor(survivingEdge));
         } else if (value() != null) {
             IntegerStamp stamp = value().integerStamp();
             if (!stamp.isUnrestricted()) {
@@ -121,7 +121,7 @@
                 }
                 if (validKeys == 0) {
                     tool.addToWorkList(defaultSuccessor());
-                    ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessorIndex());
+                    ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessor());
                 } else if (validKeys != keys.length) {
                     ArrayList<BeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
                     int[] newKeys = new int[validKeys];
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Tue Dec 18 11:27:12 2012 +0100
@@ -31,7 +31,8 @@
  * The {@code SwitchNode} class is the base of both lookup and table switches.
  */
 public abstract class SwitchNode extends ControlSplitNode {
-
+    @Successor protected final NodeSuccessorList<BeginNode> successors;
+    protected double[] successorProbabilities;
     @Input private ValueNode value;
     private final double[] keyProbabilities;
     private final int[] keySuccessors;
@@ -46,13 +47,26 @@
      * @param successors the list of successors of this switch
      */
     public SwitchNode(ValueNode value, BeginNode[] successors, double[] successorProbabilities, int[] keySuccessors, double[] keyProbabilities) {
-        super(StampFactory.forVoid(), successors, successorProbabilities);
+        super(StampFactory.forVoid());
+        this.successorProbabilities = successorProbabilities;
         assert keySuccessors.length == keyProbabilities.length;
+        this.successors = new NodeSuccessorList<>(this, successors);
         this.value = value;
         this.keySuccessors = keySuccessors;
         this.keyProbabilities = keyProbabilities;
     }
 
+    @Override
+    public double probability(BeginNode successor) {
+        double sum = 0;
+        for (int i = 0; i < successors.size(); i++) {
+            if (successors.get(i) == successor) {
+                sum += successorProbabilities[i];
+            }
+        }
+        return sum;
+    }
+
     /**
      * The number of distinct keys in this switch.
      */
@@ -74,7 +88,7 @@
      * Returns the successor for the key at the given index.
      */
     public BeginNode keySuccessor(int i) {
-        return blockSuccessor(keySuccessors[i]);
+        return successors.get(keySuccessors[i]);
     }
 
     /**
@@ -91,6 +105,18 @@
         return keySuccessors[keySuccessors.length - 1];
     }
 
+    public BeginNode blockSuccessor(int i) {
+        return successors.get(i);
+    }
+
+    public void setBlockSuccessor(int i, BeginNode s) {
+        successors.set(i, s);
+    }
+
+    public int blockSuccessorCount() {
+        return successors.count();
+    }
+
     /**
      * Gets the successor corresponding to the default (fall through) case.
      * @return the default successor
@@ -99,7 +125,7 @@
         if (defaultSuccessorIndex() == -1) {
             throw new GraalInternalError("unexpected");
         }
-        return defaultSuccessorIndex() == -1 ? null : blockSuccessor(defaultSuccessorIndex());
+        return defaultSuccessorIndex() == -1 ? null : successors.get(defaultSuccessorIndex());
     }
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Tue Dec 18 11:27:12 2012 +0100
@@ -91,7 +91,7 @@
                 }
             }
             tool.addToWorkList(blockSuccessor(survivingEdge));
-            ((StructuredGraph) graph()).removeSplitPropagate(this, survivingEdge);
+            ((StructuredGraph) graph()).removeSplit(this, blockSuccessor(survivingEdge));
         }
         if (value() instanceof LoadHubNode) {
             ObjectStamp stamp = ((LoadHubNode) value()).object().objectStamp();
@@ -104,7 +104,7 @@
                 }
                 if (validKeys == 0) {
                     tool.addToWorkList(defaultSuccessor());
-                    ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessorIndex());
+                    ((StructuredGraph) graph()).removeSplitPropagate(this, defaultSuccessor());
                 } else if (validKeys != keys.length) {
                     ArrayList<BeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
                     ResolvedJavaType[] newKeys = new ResolvedJavaType[validKeys];
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/ComputeImmediateDominator.java	Tue Dec 18 11:27:12 2012 +0100
@@ -104,7 +104,7 @@
             //TTY.println("  Already explored, propagate update");
             propagateUpdate(csInfo);
         } else {
-            if (csInfo.parentCount() == cs.blockSuccessorCount()) { // all paths leading to this CS have been explored
+            if (csInfo.parentCount() == cs.successors().count()) { // all paths leading to this CS have been explored
                 //TTY.println("  All parents explored, Enqueue");
                 toExplore.add(next);
                 speculativeExplore.remove(next);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Tue Dec 18 11:27:12 2012 +0100
@@ -244,7 +244,7 @@
         }
 
         @Override
-        public void afterSplit(FixedNode node) {
+        public void afterSplit(BeginNode node) {
             assert node.predecessor() != null;
             Node pred = node.predecessor();
             if (pred instanceof Invoke) {
@@ -255,13 +255,7 @@
             } else {
                 assert pred instanceof ControlSplitNode;
                 ControlSplitNode x = (ControlSplitNode) pred;
-                double sum = 0;
-                for (int i = 0; i < x.blockSuccessorCount(); i++) {
-                    if (x.blockSuccessor(i) == node) {
-                        sum += x.probability(i);
-                    }
-                }
-                probability *= sum;
+                probability *= x.probability(node);
             }
         }
     }
@@ -316,7 +310,7 @@
         }
 
         @Override
-        public void afterSplit(FixedNode node) {
+        public void afterSplit(BeginNode node) {
             // nothing to do...
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Dec 18 11:27:12 2012 +0100
@@ -214,7 +214,7 @@
         }
 
         @Override
-        public void afterSplit(FixedNode node) {
+        public void afterSplit(BeginNode node) {
         }
 
         @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertUnreachedToGuardPhase.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertUnreachedToGuardPhase.java	Tue Dec 18 11:27:12 2012 +0100
@@ -49,11 +49,11 @@
                 BeginNode insertGuard = null;
                 BeginNode delete = null;
                 boolean inverted = false;
-                if (ifNode.probability(IfNode.TRUE_EDGE) == 0) {
+                if (ifNode.probability(ifNode.trueSuccessor()) == 0) {
                     insertGuard = ifNode.falseSuccessor();
                     delete = ifNode.trueSuccessor();
                     inverted = true;
-                } else if (ifNode.probability(IfNode.FALSE_EDGE) == 0) {
+                } else if (ifNode.probability(ifNode.falseSuccessor()) == 0) {
                     insertGuard = ifNode.trueSuccessor();
                     delete = ifNode.falseSuccessor();
                 }
@@ -61,7 +61,7 @@
                     GuardNode guard = graph.unique(new GuardNode(ifNode.condition(), BeginNode.prevBegin(ifNode), DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, inverted, ifNode.leafGraphId()));
                     graph.addBeforeFixed(ifNode, graph.add(new ValueAnchorNode(guard)));
                     GraphUtil.killCFG(delete);
-                    graph.removeSplit(ifNode, inverted ? IfNode.FALSE_EDGE : IfNode.TRUE_EDGE);
+                    graph.removeSplit(ifNode, inverted ? ifNode.falseSuccessor() : ifNode.trueSuccessor());
                 }
             }
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CullFrameStatesPhase.java	Tue Dec 18 11:27:12 2012 +0100
@@ -87,7 +87,7 @@
         }
 
         @Override
-        public void afterSplit(FixedNode node) {
+        public void afterSplit(BeginNode node) {
         }
 
         @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java	Tue Dec 18 11:27:12 2012 +0100
@@ -149,7 +149,8 @@
 
     private static boolean eliminateAtControlSplit(ControlSplitNode controlSplit) {
         Map<Condition, Collection<GuardNode>> conditionToGuard = new HashMap<>();
-        for (BeginNode begin : controlSplit.blockSuccessors()) {
+        for (Node successor : controlSplit.successors()) {
+            BeginNode begin = (BeginNode) successor;
             for (GuardNode guard : begin.guards()) {
                 if (guard.dependencies().size() != 1) {
                     continue;
@@ -196,7 +197,7 @@
             if (leafGraphId < 0) {
                 continue;
             }
-            if (begins.size() == controlSplit.blockSuccessors().count()) {
+            if (begins.size() == controlSplit.successors().count()) {
                 hits = true;
                 Condition condition = entry.getKey();
                 GuardNode newGuard = controlSplit.graph().unique(new GuardNode(condition.conditionNode, BeginNode.prevBegin(controlSplit), reason, action, condition.negated, leafGraphId));
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Tue Dec 18 11:27:12 2012 +0100
@@ -157,7 +157,7 @@
         }
 
         @Override
-        public void afterSplit(FixedNode node) {
+        public void afterSplit(BeginNode node) {
             // nothing
         }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Tue Dec 18 11:27:12 2012 +0100
@@ -576,11 +576,11 @@
                 assert exceptionMerge != null && exceptionObjectPhi != null;
 
                 InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
-                BeginNode exceptionEdge = invokeWithException.exceptionEdge();
+                DispatchBeginNode exceptionEdge = invokeWithException.exceptionEdge();
                 ExceptionObjectNode exceptionObject = (ExceptionObjectNode) exceptionEdge.next();
                 FrameState stateAfterException = exceptionObject.stateAfter();
 
-                BeginNode newExceptionEdge = (BeginNode) exceptionEdge.copyWithInputs();
+                DispatchBeginNode newExceptionEdge = (DispatchBeginNode) exceptionEdge.copyWithInputs();
                 ExceptionObjectNode newExceptionObject = (ExceptionObjectNode) exceptionObject.copyWithInputs();
                 // set new state (pop old exception object, push new one)
                 newExceptionObject.setStateAfter(stateAfterException.duplicateModified(stateAfterException.bci, stateAfterException.rethrowException(), Kind.Object, newExceptionObject));
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Tue Dec 18 11:27:12 2012 +0100
@@ -31,5 +31,5 @@
     boolean merge(MergeNode merge, List<T> withStates);
     void loopBegin(LoopBeginNode loopBegin);
     void loopEnds(LoopBeginNode loopBegin, List<T> loopEndStates);
-    void afterSplit(FixedNode node);
+    void afterSplit(BeginNode node);
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Tue Dec 18 11:27:12 2012 +0100
@@ -38,7 +38,7 @@
 public abstract class PostOrderNodeIterator<T extends MergeableState<T>> {
 
     private final NodeBitMap visitedEnds;
-    private final Deque<FixedNode> nodeQueue;
+    private final Deque<BeginNode> nodeQueue;
     private final IdentityHashMap<FixedNode, T> nodeStates;
     private final FixedNode start;
 
@@ -109,13 +109,13 @@
             for (Node node : successors) {
                 if (node != null) {
                     nodeStates.put((FixedNode) node.predecessor(), state);
-                    nodeQueue.addFirst((FixedNode) node);
+                    nodeQueue.addFirst((BeginNode) node);
                 }
             }
         } else {
             for (Node node : x.successors()) {
                 if (node != null) {
-                    nodeQueue.addFirst((FixedNode) node);
+                    nodeQueue.addFirst((BeginNode) node);
                 }
             }
         }
@@ -124,7 +124,7 @@
     private FixedNode nextQueuedNode() {
         int maxIterations = nodeQueue.size();
         while (maxIterations-- > 0) {
-            FixedNode node = nodeQueue.removeFirst();
+            BeginNode node = nodeQueue.removeFirst();
             if (node instanceof MergeNode) {
                 MergeNode merge = (MergeNode) node;
                 state = nodeStates.get(merge.forwardEndAt(0)).clone();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Mon Dec 17 18:36:31 2012 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Tue Dec 18 11:27:12 2012 +0100
@@ -221,7 +221,7 @@
                                         InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
 
                                         invokeWithExceptionNode.killExceptionEdge();
-                                        graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
+                                        graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next());
                                     } else {
                                         graph.removeFixed((InvokeNode) invokeNode);
                                     }
@@ -381,7 +381,7 @@
                             InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
 
                             invokeWithExceptionNode.killExceptionEdge();
-                            graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
+                            graph.removeSplit(invokeWithExceptionNode, invokeWithExceptionNode.next());
                         } else {
                             graph.removeFixed((InvokeNode) invokeNode);
                         }