changeset 3480:2423a432fa6b

changes to Node structure (incomplete)
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 28 Jul 2011 08:18:43 +0200
parents be914c1e065a
children d95db56f8deb
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/OperandPool.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/PostOrderNodeIterator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ControlSplit.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionObject.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedNodeWithNext.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatingNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorAddress.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewMultiArray.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewObjectArray.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewTypeArray.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Placeholder.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Return.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Switch.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Unwind.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueAnchor.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ComputeProbabilityPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GlobalValueNumberingPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RematerializationPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/BitMap2D.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizerImpl.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java
diffstat 61 files changed, 304 insertions(+), 600 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Thu Jul 28 08:18:43 2011 +0200
@@ -74,8 +74,8 @@
             public void verificationFailed(Node n, String message) {
                 GraalCompiler.this.fireCompilationEvent(new CompilationEvent(currentCompilation, "Verification Error on Node " + n.id(), currentCompilation.graph, true, false, true));
                 TTY.println(n.toString());
-                for (Node p : n.predecessors()) {
-                    TTY.println("predecessor: " + p);
+                if (n.predecessor() != null) {
+                    TTY.println("predecessor: " + n.predecessor());
                 }
                 for (Node p : n.usages()) {
                     TTY.println("usage: " + p);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Thu Jul 28 08:18:43 2011 +0200
@@ -44,6 +44,7 @@
 import com.oracle.max.graal.compiler.value.FrameState.ValueProcedure;
 import com.oracle.max.graal.extensions.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/OperandPool.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/OperandPool.java	Thu Jul 28 08:18:43 2011 +0200
@@ -27,6 +27,7 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.ci.*;
 
 /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java	Thu Jul 28 08:18:43 2011 +0200
@@ -36,6 +36,7 @@
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ci.CiAddress.*;
 import com.sun.cri.ri.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Thu Jul 28 08:18:43 2011 +0200
@@ -33,6 +33,7 @@
 import com.oracle.max.graal.compiler.util.LoopUtil.Loop;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 /**
  * Generates a representation of {@link Graph Graphs} that can be visualized and inspected with the <a
@@ -310,7 +311,7 @@
             int toIndex = 1;
             for (Node input : node.inputs()) {
                 if (input != Node.Null && !omittedClasses.contains(input.getClass())) {
-                    edges.add(new Edge(input.id(), input.successors().size(), node.id(), toIndex));
+                    edges.add(new Edge(input.id(), input.successors().explicitCount(), node.id(), toIndex));
                 }
                 toIndex++;
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Jul 28 08:18:43 2011 +0200
@@ -296,9 +296,9 @@
             }
         }
         if (block.blockSuccessors().size() >= 1 && !block.endsWithJump()) {
-            NodeArray successors = block.lastInstruction().successors();
-            assert successors.size() >= 1 : "should have at least one successor : " + block.lastInstruction();
-            block.lir().jump(getLIRBlock((FixedNode) successors.get(0)));
+            NodeSuccessorsIterable<Node> successors = block.lastInstruction().successors();
+            assert successors.explicitCount() >= 1 : "should have at least one successor : " + block.lastInstruction();
+            block.lir().jump(getLIRBlock((FixedNode) successors.first()));
         }
 
         if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java	Thu Jul 28 08:18:43 2011 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 /**
  * The {@code PhiSimplifier} class is a helper class that can reduce phi instructions.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Thu Jul 28 08:18:43 2011 +0200
@@ -284,6 +284,6 @@
     }
 
     public FixedNodeWithNext getHIRStartBlock() {
-        return (FixedNodeWithNext) compilation.graph.start().successors().get(0);
+        return (FixedNodeWithNext) compilation.graph.start().successors().first();
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/PostOrderNodeIterator.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/PostOrderNodeIterator.java	Thu Jul 28 08:18:43 2011 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 public abstract class PostOrderNodeIterator<T extends MergeableState<T>> {
 
@@ -127,8 +128,8 @@
                     nodeQueue.addLast(merge);
                 }
             } else {
-                assert node.predecessors().size() == 1;
-                state = nodeStates.get(node.predecessors().get(0)).clone();
+                assert node.predecessor() != null;
+                state = nodeStates.get(node.predecessor()).clone();
                 state.afterSplit(node);
                 return node;
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java	Thu Jul 28 08:18:43 2011 +0200
@@ -33,19 +33,19 @@
  */
 public final class Anchor extends FixedNodeWithNext {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private final NodeInputList<GuardNode> guards = new NodeInputList<GuardNode>(this);
 
     /**
      * Constructs a new Anchor instruction.
      * @param graph
      */
     public Anchor(Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
     }
 
     public void addGuard(GuardNode x) {
-        variableInputs().add(x);
+        guards.add(x);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java	Thu Jul 28 08:18:43 2011 +0200
@@ -37,30 +37,16 @@
 public final class ArrayLength extends FloatingNode {
     private static final ArrayLengthCanonicalizerOp CANONICALIZER = new ArrayLengthCanonicalizerOp();
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_ARRAY = 0;
+    @NodeInput
+    private Value array;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Value array() {
+        return array;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction that produces the array object.
-     */
-     public Value array() {
-        return (Value) inputs().get(super.inputCount() + INPUT_ARRAY);
-    }
-
-    public Value setArray(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_ARRAY, n);
+    public void setArray(Value x) {
+        updateUsages(array, x);
+        array = x;
     }
 
     /**
@@ -69,7 +55,7 @@
      * @param newFrameState the state after executing this instruction
      */
     public ArrayLength(Value array, Graph graph) {
-        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Int, graph);
         setArray(array);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ComputeLinearScanOrder.java	Thu Jul 28 08:18:43 2011 +0200
@@ -29,6 +29,7 @@
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 public final class ComputeLinearScanOrder {
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ControlSplit.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ControlSplit.java	Thu Jul 28 08:18:43 2011 +0200
@@ -33,33 +33,19 @@
  */
 public abstract class ControlSplit extends FixedNode {
 
-    private static final int INPUT_COUNT = 0;
+    @NodeSuccessor
+    private final NodeSuccessorList<FixedNode> blockSuccessors;
 
-    private static final int SUCCESSOR_COUNT = 0;
-    private final int blockSuccessorCount;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public FixedNode blockSuccessor(int index) {
+        return blockSuccessors.get(index);
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + blockSuccessorCount + SUCCESSOR_COUNT;
-    }
-
-    public FixedNode blockSuccessor(int index) {
-        assert index >= 0 && index < blockSuccessorCount;
-        return (FixedNode) successors().get(super.successorCount() + SUCCESSOR_COUNT + index);
-    }
-
-    public FixedNode setBlockSuccessor(int index, FixedNode n) {
-        assert index >= 0 && index < blockSuccessorCount;
-        return (FixedNode) successors().set(super.successorCount() + SUCCESSOR_COUNT + index, n);
+    public void setBlockSuccessor(int index, FixedNode x) {
+        blockSuccessors.set(index, x);
     }
 
     public int blockSuccessorCount() {
-        return blockSuccessorCount;
+        return blockSuccessors.size();
     }
 
     protected final double[] branchProbability;
@@ -69,16 +55,16 @@
      * @param kind the type of the value produced by this instruction
      * @param successors the list of successor blocks. If {@code null}, a new one will be created.
      */
-    public ControlSplit(CiKind kind, List<? extends FixedNode> blockSuccessors, double[] branchProbability, int inputCount, int successorCount, Graph graph) {
-        this(kind, blockSuccessors.size(), branchProbability, inputCount, successorCount, graph);
+    public ControlSplit(CiKind kind, List<? extends FixedNode> blockSuccessors, double[] branchProbability, Graph graph) {
+        this(kind, blockSuccessors.size(), branchProbability, graph);
         for (int i = 0; i < blockSuccessors.size(); i++) {
             setBlockSuccessor(i, blockSuccessors.get(i));
         }
     }
 
-    public ControlSplit(CiKind kind, int blockSuccessorCount, double[] branchProbability, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount + INPUT_COUNT, successorCount + blockSuccessorCount + SUCCESSOR_COUNT, graph);
-        this.blockSuccessorCount = blockSuccessorCount;
+    public ControlSplit(CiKind kind, int blockSuccessorCount, double[] branchProbability, Graph graph) {
+        super(kind, graph);
+        this.blockSuccessors = new NodeSuccessorList<FixedNode>(this, blockSuccessorCount);
         assert branchProbability.length == blockSuccessorCount;
         this.branchProbability = branchProbability;
     }
@@ -96,7 +82,7 @@
      * @return the default successor
      */
     public FixedNode defaultSuccessor() {
-        return blockSuccessor(blockSuccessorCount - 1);
+        return blockSuccessor(blockSuccessorCount() - 1);
     }
 
     public Iterable<FixedNode> blockSuccessors() {
@@ -116,7 +102,7 @@
 
                     @Override
                     public boolean hasNext() {
-                        return i < ControlSplit.this.blockSuccessorCount;
+                        return i < ControlSplit.this.blockSuccessorCount();
                     }
                 };
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Thu Jul 28 08:18:43 2011 +0200
@@ -30,9 +30,6 @@
 
 public class Deoptimize extends FixedNode {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     public static enum DeoptAction {
         None,                           // just interpret, do not invalidate nmethod
         Recompile,                      // recompile the nmethod; need not invalidate
@@ -45,7 +42,7 @@
     private final DeoptAction action;
 
     public Deoptimize(DeoptAction action, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
         this.action = action;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Thu Jul 28 08:18:43 2011 +0200
@@ -30,11 +30,9 @@
 
 
 public final class EndNode extends FixedNode {
-    public static final int SUCCESSOR_COUNT = 0;
-    public static final int INPUT_COUNT = 0;
 
     public EndNode(Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
     }
 
     @Override
@@ -65,10 +63,7 @@
 
     @Override
     public boolean verify() {
-        assertTrue(inputs().size() == 0, "inputs empty");
-        assertTrue(successors().size() == 0, "successors empty");
         assertTrue(usages().size() <= 1, "at most one usage");
-        assertTrue(predecessors().size() <= 1, "at most one predecessor " + predecessors());
         return true;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionObject.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionObject.java	Thu Jul 28 08:18:43 2011 +0200
@@ -31,16 +31,12 @@
  */
 public final class ExceptionObject extends StateSplit {
 
-    private static final int INPUT_COUNT = 0;
-
-    private static final int SUCCESSOR_COUNT = 0;
-
     /**
      * Constructs a new ExceptionObject instruction.
      * @param graph
      */
     public ExceptionObject(Graph graph) {
-        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Object, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Thu Jul 28 08:18:43 2011 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
-import java.util.*;
-
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction;
@@ -33,8 +31,9 @@
 
 
 public final class FixedGuard extends FixedNodeWithNext {
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
+
+    @NodeInput
+    private final NodeInputList<BooleanNode> conditions = new NodeInputList<BooleanNode>(this);
 
     public FixedGuard(BooleanNode node, Graph graph) {
         this(graph);
@@ -42,7 +41,7 @@
     }
 
     public FixedGuard(Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
     }
 
     @Override
@@ -55,8 +54,8 @@
         out.print("clip node ").print(inputs().toString());
     }
 
-    public void addNode(BooleanNode node) {
-        variableInputs().add(node);
+    public void addNode(BooleanNode x) {
+        conditions.add(x);
     }
 
     @Override
@@ -79,16 +78,14 @@
         @Override
         public Node canonical(Node node) {
             FixedGuard fixedGuard = (FixedGuard) node;
-            Iterator<Node> iter = fixedGuard.variableInputs().iterator();
-            while (iter.hasNext()) {
-                Node n = iter.next();
+            for (BooleanNode n : fixedGuard.conditions.snapshot()) {
                 if (n instanceof Constant) {
                     Constant c = (Constant) n;
                     if (c.asConstant().asBoolean()) {
                         if (GraalOptions.TraceCanonicalizer) {
                             TTY.println("Removing redundant fixed guard " + fixedGuard);
                         }
-                        iter.remove();
+                        fixedGuard.conditions.remove(n);
                     } else {
                         if (GraalOptions.TraceCanonicalizer) {
                             TTY.println("Replacing fixed guard " + fixedGuard + " with deoptimization node");
@@ -98,7 +95,7 @@
                 }
             }
 
-            if (fixedGuard.variableInputs().size() == 0) {
+            if (fixedGuard.conditions.isEmpty()) {
                 return fixedGuard.next();
             }
             return fixedGuard;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedNode.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedNode.java	Thu Jul 28 08:18:43 2011 +0200
@@ -31,8 +31,8 @@
 
     private double probability;
 
-    public FixedNode(CiKind kind, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount, successorCount, graph);
+    public FixedNode(CiKind kind, Graph graph) {
+        super(kind, graph);
     }
 
     public double probability() {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedNodeWithNext.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedNodeWithNext.java	Thu Jul 28 08:18:43 2011 +0200
@@ -27,31 +27,16 @@
 
 public abstract class FixedNodeWithNext extends FixedNode {
 
-    private static final int INPUT_COUNT = 0;
+    @NodeSuccessor
+    private FixedNode next;
 
-    private static final int SUCCESSOR_COUNT = 1;
-    public static final int SUCCESSOR_NEXT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public FixedNode next() {
+        return next;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * Links to next instruction in a basic block, to {@code null} if this instruction is the end of a basic block or to
-     * itself if not in a block.
-     */
-    public FixedNode next() {
-        return (FixedNode) successors().get(super.successorCount() + SUCCESSOR_NEXT);
-    }
-
-    public Node setNext(FixedNode next) {
-        return successors().set(super.successorCount() + SUCCESSOR_NEXT, next);
+    public void setNext(FixedNode x) {
+        updatePredecessors(next, x);
+        next = x;
     }
 
     public static final int SYNCHRONIZATION_ENTRY_BCI = -1;
@@ -59,10 +44,8 @@
     /**
      * Constructs a new instruction with the specified value type.
      * @param kind the value type for this instruction
-     * @param inputCount
-     * @param successorCount
      */
-    public FixedNodeWithNext(CiKind kind, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public FixedNodeWithNext(CiKind kind, Graph graph) {
+        super(kind, graph);
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatingNode.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatingNode.java	Thu Jul 28 08:18:43 2011 +0200
@@ -28,14 +28,8 @@
 
 public abstract class FloatingNode extends Value {
 
-    /**
-     * @param kind
-     * @param inputCount
-     * @param successorCount
-     * @param graph
-     */
-    public FloatingNode(CiKind kind, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount, successorCount, graph);
+    public FloatingNode(CiKind kind, Graph graph) {
+        super(kind, graph);
     }
 
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Thu Jul 28 08:18:43 2011 +0200
@@ -34,34 +34,20 @@
  */
 public final class If extends ControlSplit {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_COMPARE = 0;
+    @NodeInput
+    private BooleanNode compare;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public BooleanNode compare() {
+        return compare;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction that produces the first input to this comparison.
-     */
-     public BooleanNode compare() {
-        return (BooleanNode) inputs().get(super.inputCount() + INPUT_COMPARE);
-    }
-
-    public void setCompare(BooleanNode n) {
-        inputs().set(super.inputCount() + INPUT_COMPARE, n);
+    public void setCompare(BooleanNode x) {
+        updateUsages(compare, x);
+        compare = x;
     }
 
     public If(BooleanNode condition, double probability, Graph graph) {
-        super(CiKind.Illegal, 2, new double[] {probability, 1 - probability}, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, 2, new double[] {probability, 1 - probability}, graph);
         setCompare(condition);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java	Thu Jul 28 08:18:43 2011 +0200
@@ -131,12 +131,6 @@
     }
 
     @Override
-    public Node singlePredecessor() {
-        assert endCount() == 1;
-        return endAt(0).singlePredecessor();
-    }
-
-    @Override
     public Iterable< ? extends Node> dataUsages() {
         final Iterator< ? extends Node> dataUsages = super.dataUsages().iterator();
         return new Iterable<Node>() {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java	Thu Jul 28 08:18:43 2011 +0200
@@ -31,34 +31,20 @@
 
 public class LoopEnd extends FixedNode {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_LOOP_BEGIN = 0;
+    @NodeInput
+    private LoopBegin loopBegin;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public LoopBegin loopBegin() {
+        return loopBegin;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction which produces the input value to this instruction.
-     */
-     public LoopBegin loopBegin() {
-        return (LoopBegin) inputs().get(super.inputCount() + INPUT_LOOP_BEGIN);
-    }
-
-    public LoopBegin setLoopBegin(LoopBegin n) {
-        return (LoopBegin) inputs().set(super.inputCount() + INPUT_LOOP_BEGIN, n);
+    public void setLoopBegin(LoopBegin x) {
+        updateUsages(this.loopBegin, x);
+        this.loopBegin = x;
     }
 
     public LoopEnd(Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Thu Jul 28 08:18:43 2011 +0200
@@ -37,18 +37,11 @@
  */
 public class Merge extends StateSplit{
 
-    private static final int INPUT_COUNT = 0;
-
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private final NodeInputList<EndNode> ends = new NodeInputList<EndNode>(this);
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
-
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public Merge(Graph graph) {
+        super(CiKind.Illegal, graph);
     }
 
     @Override
@@ -56,20 +49,6 @@
         return false;
     }
 
-    /**
-     * Constructs a new Merge at the specified bytecode index.
-     * @param bci the bytecode index of the start
-     * @param blockID the ID of the block
-     * @param graph
-     */
-    public Merge(Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-    }
-
-    protected Merge(int inputCount, int successorCount, Graph graph) {
-        super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
-    }
-
     @Override
     public void accept(ValueVisitor v) {
         v.visitMerge(this);
@@ -77,19 +56,19 @@
 
     public int endIndex(EndNode end) {
         assert variableInputs().contains(end);
-        return variableInputs().indexOf(end);
+        return ends.indexOf(end);
     }
 
     public void addEnd(EndNode end) {
-        variableInputs().add(end);
+        ends.add(end);
     }
 
     public int endCount() {
-        return variableInputs().size();
+        return ends.size();
     }
 
     public EndNode endAt(int index) {
-        return (EndNode) variableInputs().get(index);
+        return ends.get(index);
     }
 
     @Override
@@ -312,9 +291,9 @@
     }
 
     public void removeEnd(EndNode pred) {
-        int predIndex = variableInputs().indexOf(pred);
+        int predIndex = ends.indexOf(pred);
         assert predIndex != -1;
-        variableInputs().remove(predIndex);
+        ends.remove(predIndex);
 
         for (Node usage : usages()) {
             if (usage instanceof Phi) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorAddress.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorAddress.java	Thu Jul 28 08:18:43 2011 +0200
@@ -33,13 +33,10 @@
  */
 public final class MonitorAddress extends Value {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     private int monitorIndex;
 
     public MonitorAddress(int monitorIndex, Graph graph) {
-        super(CiKind.Word, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Word, graph);
         this.monitorIndex = monitorIndex;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Thu Jul 28 08:18:43 2011 +0200
@@ -35,41 +35,25 @@
  */
 public abstract class NewArray extends FixedNodeWithNext {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_LENGTH = 0;
+    @NodeInput
+    private Value length;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Value length() {
+        return length;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction that produces the length of this array.
-     */
-     public Value length() {
-        return (Value) inputs().get(super.inputCount() + INPUT_LENGTH);
-    }
-
-    public Value setLength(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_LENGTH, n);
+    public void setLength(Value x) {
+        updateUsages(this.length, x);
+        this.length = x;
     }
 
     /**
      * Constructs a new NewArray instruction.
      * @param length the instruction that produces the length for this allocation
-     * @param inputCount
-     * @param successorCount
      * @param graph
      */
-    NewArray(Value length, int inputCount, int successorCount, Graph graph) {
-        super(CiKind.Object, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    NewArray(Value length, Graph graph) {
+        super(CiKind.Object, graph);
         setLength(length);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Thu Jul 28 08:18:43 2011 +0200
@@ -36,9 +36,6 @@
  */
 public final class NewInstance extends FixedNodeWithNext {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     final RiType instanceClass;
     public final int cpi;
     public final RiConstantPool constantPool;
@@ -50,7 +47,7 @@
      * @param graph
      */
     public NewInstance(RiType type, int cpi, RiConstantPool constantPool, Graph graph) {
-        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Object, graph);
         this.instanceClass = type;
         this.cpi = cpi;
         this.constantPool = constantPool;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewMultiArray.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewMultiArray.java	Thu Jul 28 08:18:43 2011 +0200
@@ -33,32 +33,16 @@
  */
 public final class NewMultiArray extends NewArray {
 
-    private final int dimensionCount;
-
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + dimensionCount;
-    }
+    @NodeInput
+    private final NodeInputList<Value> dimensions;
 
     @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public Value dimension(int index) {
+        return dimensions.get(index);
     }
 
-    /**
-     * The list of instructions which produce input for this instruction.
-     */
-    @Override
-    public Value dimension(int index) {
-        assert index >= 0 && index < dimensionCount;
-        return (Value) inputs().get(super.inputCount() + index);
-    }
-
-    public Value setDimension(int index, Value n) {
-        assert index >= 0 && index < dimensionCount;
-        return (Value) inputs().set(super.inputCount() + index, n);
+    public void setDimension(int index, Value x) {
+        dimensions.set(index, x);
     }
 
     /**
@@ -66,7 +50,7 @@
      */
     @Override
     public int dimensionCount() {
-        return dimensionCount;
+        return dimensions.size();
     }
 
     public final RiType elementType;
@@ -82,12 +66,12 @@
      * @param graph
      */
     public NewMultiArray(RiType elementType, Value[] dimensions, int cpi, RiConstantPool riConstantPool, Graph graph) {
-        super(null, dimensions.length, SUCCESSOR_COUNT, graph);
+        super(null, graph);
         this.constantPool = riConstantPool;
         this.elementType = elementType;
         this.cpi = cpi;
 
-        this.dimensionCount = dimensions.length;
+        this.dimensions = new NodeInputList<Value>(this, dimensions.length);
         for (int i = 0; i < dimensions.length; i++) {
             setDimension(i, dimensions[i]);
         }
@@ -124,7 +108,7 @@
     @Override
     public void print(LogStream out) {
         out.print("new multi array [");
-        for (int i = 0; i < dimensionCount; i++) {
+        for (int i = 0; i < dimensionCount(); i++) {
           if (i > 0) {
               out.print(", ");
           }
@@ -135,7 +119,7 @@
 
     @Override
     public Node copy(Graph into) {
-        NewMultiArray x = new NewMultiArray(elementType, new Value[dimensionCount], cpi, constantPool, into);
+        NewMultiArray x = new NewMultiArray(elementType, new Value[dimensionCount()], cpi, constantPool, into);
         super.copyInto(x);
         return x;
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewObjectArray.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewObjectArray.java	Thu Jul 28 08:18:43 2011 +0200
@@ -32,9 +32,6 @@
  */
 public final class NewObjectArray extends NewArray {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     final RiType elementClass;
 
     /**
@@ -44,7 +41,7 @@
      * @param graph
      */
     public NewObjectArray(RiType elementClass, Value length, Graph graph) {
-        super(length, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(length, graph);
         this.elementClass = elementClass;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewTypeArray.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewTypeArray.java	Thu Jul 28 08:18:43 2011 +0200
@@ -32,13 +32,10 @@
  */
 public final class NewTypeArray extends NewArray {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     final RiType elementType;
 
     public NewTypeArray(Value length, RiType elementType, Graph graph) {
-        super(length, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(length, graph);
         this.elementType = elementType;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Placeholder.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Placeholder.java	Thu Jul 28 08:18:43 2011 +0200
@@ -29,22 +29,8 @@
 
 public class Placeholder extends StateSplit {
 
-    private static final int INPUT_COUNT = 0;
-
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
-
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
     public Placeholder(Graph graph) {
-        super(CiKind.Void, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Void, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Thu Jul 28 08:18:43 2011 +0200
@@ -35,34 +35,20 @@
  */
 public final class RegisterFinalizer extends StateSplit {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_OBJECT = 0;
+    @NodeInput
+    private Value object;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Value object() {
+        return object;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction that produces the object whose finalizer should be registered.
-     */
-     public Value object() {
-        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
-    }
-
-    public Value setObject(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    public void setObject(Value x) {
+        updateUsages(object, x);
+        object = x;
     }
 
     public RegisterFinalizer(Value object, Graph graph) {
-        super(CiKind.Void, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Void, graph);
         setObject(object);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Return.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Return.java	Thu Jul 28 08:18:43 2011 +0200
@@ -31,31 +31,16 @@
  */
 public final class Return extends FixedNode {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_RESULT = 0;
+    @NodeInput
+    private Value result;
 
-    private static final int SUCCESSOR_COUNT = 1;
-    private static final int SUCCESSOR_END = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Value result() {
+        return result;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction that produces the result for the return.
-     */
-     public Value result() {
-        return (Value) inputs().get(super.inputCount() + INPUT_RESULT);
-    }
-
-    public Value setResult(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_RESULT, n);
+    public void setResult(Value x) {
+        updateUsages(this.result, x);
+        this.result = x;
     }
 
     /**
@@ -65,13 +50,13 @@
      * @param graph
      */
     public Return(Value result, Graph graph) {
-        super(result == null ? CiKind.Void : result.kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(result == null ? CiKind.Void : result.kind, graph);
         setResult(result);
     }
 
     // for copying
     private Return(CiKind kind, Graph graph) {
-        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Thu Jul 28 08:18:43 2011 +0200
@@ -34,41 +34,25 @@
  */
 public abstract class StateSplit extends FixedNodeWithNext {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_STATE_AFTER = 0;
+    @NodeInput
+    private FrameState stateAfter;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public FrameState stateAfter() {
+        return stateAfter;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The state for this instruction.
-     */
-    public FrameState stateAfter() {
-        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER);
-    }
-
-    public void setStateAfter(FrameState n) {
-        inputs().set(super.inputCount() + INPUT_STATE_AFTER, n);
+    public void setStateAfter(FrameState x) {
+        updateUsages(stateAfter, x);
+        stateAfter = x;
     }
 
     /**
      * Creates a new state split with the specified value type.
      * @param kind the type of the value that this instruction produces
-     * @param inputCount
-     * @param successorCount
      * @param graph
      */
-    public StateSplit(CiKind kind, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public StateSplit(CiKind kind, Graph graph) {
+        super(kind, graph);
     }
 
     public boolean needsStateAfter() {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Switch.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Switch.java	Thu Jul 28 08:18:43 2011 +0200
@@ -32,30 +32,16 @@
  */
 public abstract class Switch extends ControlSplit {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_VALUE = 0;
+    @NodeInput
+    private Value value;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Value value() {
+        return value;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction that provides the input value to this switch.
-     */
-     public Value value() {
-        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
-    }
-
-    public Value setValue(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_VALUE, n);
+    public void setValue(Value x) {
+        updateUsages(value, x);
+        value = x;
     }
 
     /**
@@ -66,7 +52,7 @@
      * @param graph
      */
     public Switch(Value value, List<? extends FixedNode> successors, double[] probability, int inputCount, int successorCount, Graph graph) {
-        super(CiKind.Illegal, successors, probability, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, successors, probability, graph);
         setValue(value);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Unwind.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Unwind.java	Thu Jul 28 08:18:43 2011 +0200
@@ -31,35 +31,21 @@
  */
 public final class Unwind extends FixedNode {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_EXCEPTION = 0;
+    @NodeInput
+    private Value exception;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Value exception() {
+        return exception;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction that produces the exception object.
-     */
-     public Value exception() {
-        return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION);
-    }
-
-    public Value setException(Value n) {
-        assert n == null || n.kind == CiKind.Object;
-        return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
+    public void setException(Value x) {
+        assert x == null || x.kind == CiKind.Object;
+        updateUsages(this.exception, x);
+        this.exception = x;
     }
 
     public Unwind(Value exception, Graph graph) {
-        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Object, graph);
         setException(exception);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Thu Jul 28 08:18:43 2011 +0200
@@ -51,8 +51,8 @@
      * @param successorCount
      * @param graph
      */
-    public Value(CiKind kind, int inputCount, int successorCount, Graph graph) {
-        super(inputCount, successorCount, graph);
+    public Value(CiKind kind, Graph graph) {
+        super(graph);
         assert kind != null && kind == kind.stackKind() : kind + " != " + kind.stackKind();
         this.kind = kind;
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueAnchor.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueAnchor.java	Thu Jul 28 08:18:43 2011 +0200
@@ -31,39 +31,20 @@
  */
 public final class ValueAnchor extends FixedNodeWithNext {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_OBJECT = 0;
-
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private Value object;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
-
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public Value object() {
+        return object;
     }
 
-    /**
-     * The instruction that should be scheduled before this anchor.
-     */
-     public Value object() {
-        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    public void setObject(Value x) {
+        updateUsages(object, x);
+        object = x;
     }
 
-    public Value setObject(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
-    }
-
-    /**
-     * Constructs a new Anchor instruction.
-     * @param succ the successor block of the anchor
-     * @param graph
-     */
     public ValueAnchor(Value object, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
         setObject(object);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java	Thu Jul 28 08:18:43 2011 +0200
@@ -31,6 +31,7 @@
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 /**
  * The {@code LIRBlock} class definition.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java	Thu Jul 28 08:18:43 2011 +0200
@@ -26,6 +26,7 @@
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.ci.*;
 
 /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Thu Jul 28 08:18:43 2011 +0200
@@ -29,6 +29,7 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.lir.LIROperand.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.ci.*;
 
 /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 public class CanonicalizerPhase extends Phase {
     private static final int MAX_ITERATION_PER_NODE = 10;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ComputeProbabilityPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ComputeProbabilityPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -202,8 +202,8 @@
 
         @Override
         public void afterSplit(FixedNode node) {
-            assert node.predecessors().size() == 1;
-            Node pred = node.predecessors().get(0);
+            assert node.predecessor() != null;
+            Node pred = node.predecessor();
             if (pred instanceof Invoke) {
                 Invoke x = (Invoke) pred;
                 if (x.next() != node) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -29,6 +29,7 @@
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 
 public class DeadCodeEliminationPhase extends Phase {
@@ -45,7 +46,6 @@
         iterateSuccessors();
         disconnectCFGNodes();
         iterateInputs();
-        disconnectNodes();
         deleteNodes();
 
         // remove chained Merges
@@ -99,8 +99,9 @@
                         }
                         ((LoopEnd) node).setLoopBegin(null);
                         EndNode endNode = loop.endAt(0);
-                        assert endNode.predecessors().size() == 1 : endNode.predecessors().size();
-                        replacePhis(loop);
+                        assert endNode.predecessor() != null;
+                        // replacePhis(loop);
+
                         endNode.replaceAndDelete(loop.next());
                         loop.delete();
                     }
@@ -110,7 +111,7 @@
     }
 
     private void replacePhis(Merge merge) {
-        for (Node usage : new ArrayList<Node>(merge.usages())) {
+        for (Node usage : merge.usages().snapshot()) {
             assert usage instanceof Phi;
             usage.replaceAndDelete(((Phi) usage).valueAt(0));
         }
@@ -119,12 +120,7 @@
     private void deleteNodes() {
         for (Node node : graph.getNodes()) {
             if (!flood.isMarked(node)) {
-                for (int i = 0; i < node.inputs().size(); i++) {
-                    node.inputs().set(i, Node.Null);
-                }
-                for (int i = 0; i < node.successors().size(); i++) {
-                    node.successors().set(i, Node.Null);
-                }
+                node.clearEdges();
             }
         }
         for (Node node : graph.getNodes()) {
@@ -152,16 +148,4 @@
         }
     }
 
-    private void disconnectNodes() {
-        for (Node node : graph.getNodes()) {
-            if (!flood.isMarked(node)) {
-                for (int i = 0; i < node.inputs().size(); i++) {
-                    Node input = node.inputs().get(i);
-                    if (input != Node.Null && flood.isMarked(input)) {
-                        node.inputs().set(i, Node.Null);
-                    }
-                }
-            }
-        }
-    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -197,8 +197,7 @@
         }
 
         private void process() {
-            ArrayList<Node> arrayList = new ArrayList<Node>(node.usages());
-            for (Node usage : arrayList) {
+            for (Node usage : node.usages().snapshot()) {
                 op.beforeUpdate(node, usage);
             }
         }
@@ -353,7 +352,7 @@
                 return false;
             } else if (usage instanceof FrameState) {
                 FrameState x = (FrameState) usage;
-                assert x.inputs().contains(node);
+                assert x.inputContains(node);
                 return true;
             } else if (usage instanceof AccessMonitor) {
                 AccessMonitor x = (AccessMonitor) usage;
@@ -369,19 +368,13 @@
         public void beforeUpdate(Node node, Node usage) {
             if (usage instanceof IsNonNull) {
                 IsNonNull x = (IsNonNull) usage;
-                if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) {
-                    FixedGuard guard = (FixedGuard) x.usages().get(0);
-                    guard.replaceAndDelete(guard.next());
-                }
-                x.delete();
+                // TODO (ls) not sure about this...
+                x.replaceAndDelete(Constant.forBoolean(true, node.graph()));
             } else if (usage instanceof IsType) {
                 IsType x = (IsType) usage;
                 assert x.type() == ((Value) node).exactType();
-                if (x.usages().size() == 1 && x.usages().get(0) instanceof FixedGuard) {
-                    FixedGuard guard = (FixedGuard) x.usages().get(0);
-                    guard.replaceAndDelete(guard.next());
-                }
-                x.delete();
+                // TODO (ls) not sure about this...
+                x.replaceAndDelete(Constant.forBoolean(true, node.graph()));
             } else if (usage instanceof AccessMonitor) {
                 AccessMonitor x = (AccessMonitor) usage;
                 x.replaceAndDelete(x.next());
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GlobalValueNumberingPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GlobalValueNumberingPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -25,6 +25,7 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 /**
  * Duplicates every node in the graph to test the implementation of the {@link com.oracle.max.graal.graph.Node#copy()} method in node subclasses.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -42,6 +42,7 @@
 import com.oracle.max.graal.compiler.util.LoopUtil.Loop;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -206,7 +207,7 @@
         // remove FrameStates
         for (Node n : graph.getNodes()) {
             if (n instanceof FrameState) {
-                if (n.usages().size() == 0 && n.predecessors().size() == 0) {
+                if (n.usages().size() == 0 && n.predecessor() == null) {
                     n.delete();
                 }
             }
@@ -284,7 +285,7 @@
         StateSplit first = (StateSplit) target.firstInstruction;
 
         if (target.isLoopHeader && isVisited(target)) {
-            first = (StateSplit) loopBegin(target).loopEnd().singlePredecessor();
+            first = (StateSplit) loopBegin(target).loopEnd().predecessor();
         }
 
         int bci = target.startBci;
@@ -309,12 +310,11 @@
 
             if (first instanceof Placeholder) {
                 Placeholder p = (Placeholder) first;
-                if (p.predecessors().size() == 0) {
+                if (p.predecessor() == null) {
                     p.setStateAfter(newState.duplicate(bci));
                     return;
                 } else {
                     Merge merge = new Merge(graph);
-                    assert p.predecessors().size() == 1 : "predecessors size: " + p.predecessors().size();
                     FixedNode next = p.next();
                     EndNode end = new EndNode(graph);
                     p.setNext(end);
@@ -1114,14 +1114,14 @@
     }
 
     private Value append(FixedNode fixed) {
-        if (fixed instanceof Deoptimize && lastInstr.predecessors().size() > 0) {
+        if (fixed instanceof Deoptimize && lastInstr.predecessor() != null) {
             Node cur = lastInstr;
             Node prev = cur;
             while (cur != cur.graph().start() && !(cur instanceof ControlSplit)) {
-                assert cur.predecessors().size() == 1;
+                assert cur.predecessor() != null;
                 prev = cur;
-                cur = cur.predecessors().get(0);
-                if (cur.predecessors().size() == 0) {
+                cur = cur.predecessor();
+                if (cur.predecessor() == null) {
                     break;
                 }
 
@@ -1161,7 +1161,7 @@
     }
 
     private Value appendWithBCI(FixedNodeWithNext x) {
-        assert x.predecessors().size() == 0 : "instruction should not have been appended yet";
+        assert x.predecessor() == null : "instruction should not have been appended yet";
         assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")";
         lastInstr.setNext(x);
         lastInstr = x;
@@ -1202,7 +1202,7 @@
 
         FixedNode result = null;
         if (block.isLoopHeader && isVisited(block)) {
-            result = (StateSplit) loopBegin(block).loopEnd().singlePredecessor();
+            result = (StateSplit) loopBegin(block).loopEnd().predecessor();
         } else {
             result = block.firstInstruction;
         }
@@ -1283,7 +1283,7 @@
             if (b.isLoopHeader) {
                 LoopBegin begin = loopBegin(b);
                 LoopEnd loopEnd = begin.loopEnd();
-                StateSplit loopEndPred = (StateSplit) loopEnd.singlePredecessor();
+                StateSplit loopEndPred = (StateSplit) loopEnd.predecessor();
 
 //              This can happen with degenerated loops like this one:
 //                for (;;) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -183,8 +183,8 @@
                 if (concrete != null && checkTargetConditions(concrete, iterations) && checkSizeConditions(parent, iterations, concrete, invoke, profile, ratio)) {
                     IsType isType = new IsType(invoke.receiver(), profile.types[0], compilation.graph);
                     FixedGuard guard = new FixedGuard(isType, graph);
-                    assert invoke.predecessors().size() == 1;
-                    invoke.predecessors().get(0).successors().replace(invoke, guard);
+                    assert invoke.predecessor() != null;
+                    invoke.predecessor().replaceFirstSuccessor(invoke, guard);
                     guard.setNext(invoke);
 
                     if (GraalOptions.TraceInlining) {
@@ -245,7 +245,7 @@
             }
             return false;
         }
-        if (invoke.predecessors().size() == 0) {
+        if (invoke.predecessor() == null) {
             if (GraalOptions.TraceInlining) {
                 TTY.println("not inlining %s because the invoke is dead code", methodName(invoke.target, invoke));
             }
@@ -453,7 +453,7 @@
             }
         }
 
-        invoke.inputs().clearAll();
+        invoke.clearInputs();
 
         HashMap<Node, Node> replacements = new HashMap<Node, Node>();
         ArrayList<Node> nodes = new ArrayList<Node>();
@@ -482,8 +482,8 @@
             TTY.println("inlining %s: %d frame states, %d nodes", methodName(method), frameStates.size(), nodes.size());
         }
 
-        assert invoke.successors().get(0) != null : invoke;
-        assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size();
+        assert invoke.successors().first() != null : invoke;
+        assert invoke.predecessor() != null;
         FixedNodeWithNext pred;
         if (withReceiver) {
             pred = new FixedGuard(new IsNonNull(parameters[0], compilation.graph), compilation.graph);
@@ -534,16 +534,15 @@
         }
 
         if (returnNode != null) {
-            List<Node> usages = new ArrayList<Node>(invoke.usages());
-            for (Node usage : usages) {
+            for (Node usage : invoke.usages().snapshot()) {
                 if (returnNode.result() instanceof Local) {
-                    usage.inputs().replace(invoke, replacements.get(returnNode.result()));
+                    usage.replaceFirstInput(invoke, replacements.get(returnNode.result()));
                 } else {
-                    usage.inputs().replace(invoke, duplicates.get(returnNode.result()));
+                    usage.replaceFirstInput(invoke, duplicates.get(returnNode.result()));
                 }
             }
             Node returnDuplicate = duplicates.get(returnNode);
-            returnDuplicate.inputs().clearAll();
+            returnDuplicate.clearInputs();
             Node n = invoke.next();
             invoke.setNext(null);
             returnDuplicate.replaceAndDelete(n);
@@ -551,16 +550,15 @@
 
         if (exceptionEdge != null) {
             if (unwindNode != null) {
-                assert unwindNode.predecessors().size() == 1;
-                assert exceptionEdge.successors().size() == 1;
+                assert unwindNode.predecessor()!= null;
+                assert exceptionEdge.successors().explicitCount() == 1;
                 ExceptionObject obj = (ExceptionObject) exceptionEdge;
 
                 Unwind unwindDuplicate = (Unwind) duplicates.get(unwindNode);
-                List<Node> usages = new ArrayList<Node>(obj.usages());
-                for (Node usage : usages) {
-                    usage.inputs().replace(obj, unwindDuplicate.exception());
+                for (Node usage : obj.usages().snapshot()) {
+                    usage.replaceFirstInput(obj, unwindDuplicate.exception());
                 }
-                unwindDuplicate.inputs().clearAll();
+                unwindDuplicate.clearInputs();
                 Node n = obj.next();
                 obj.setNext(null);
                 unwindDuplicate.replaceAndDelete(n);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -32,6 +32,7 @@
 import com.oracle.max.graal.compiler.util.LoopUtil.Loop;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.ci.*;
 
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -31,6 +31,7 @@
 import com.oracle.max.graal.compiler.ir.Phi.*;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.ci.*;
 
 public class MemoryPhase extends Phase {
@@ -232,21 +233,20 @@
         }
 
         public void replaceCheckPoint(Node loopCheckPoint) {
-            List<Node> usages = new ArrayList<Node>(loopCheckPoint.usages());
-            for (Node n : usages) {
+            for (Node n : loopCheckPoint.usages().snapshot()) {
                 replaceCheckPoint(loopCheckPoint, n);
             }
         }
 
         private void replaceCheckPoint(Node loopCheckPoint, Node n) {
             if (n instanceof ReadNode) {
-                n.inputs().replace(loopCheckPoint, getLocationForRead((ReadNode) n));
+                n.replaceFirstInput(loopCheckPoint, getLocationForRead((ReadNode) n));
             } else if (n instanceof WriteNode) {
-                n.inputs().replace(loopCheckPoint, getLocationForWrite((WriteNode) n));
+                n.replaceFirstInput(loopCheckPoint, getLocationForWrite((WriteNode) n));
             } else if (n instanceof WriteMemoryCheckpointNode) {
-                n.inputs().replace(loopCheckPoint, mergeForWrite);
+                n.replaceFirstInput(loopCheckPoint, mergeForWrite);
             } else {
-                n.inputs().replace(loopCheckPoint, mergeForRead);
+                n.replaceFirstInput(loopCheckPoint, mergeForRead);
             }
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RematerializationPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RematerializationPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -30,6 +30,7 @@
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 
 public class RematerializationPhase extends Phase {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Thu Jul 28 08:18:43 2011 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 
 public class Block {
@@ -108,10 +109,9 @@
             } else {
                 assert !(firstNode instanceof Anchor);
                 Anchor a = new Anchor(firstNode.graph());
-                assert firstNode.predecessors().size() == 1 : firstNode;
-                Node pred = firstNode.predecessors().get(0);
-                int predIndex = pred.successors().indexOf(firstNode);
-                pred.successors().set(predIndex, a);
+                assert firstNode.predecessor() != null : firstNode;
+                Node pred = firstNode.predecessor();
+                pred.replaceFirstSuccessor(firstNode, a);
                 a.setNext((FixedNode) firstNode);
                 this.anchor = a;
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Thu Jul 28 08:18:43 2011 +0200
@@ -30,6 +30,7 @@
 import com.oracle.max.graal.compiler.phases.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 
 public class IdentifyBlocksPhase extends Phase {
@@ -140,12 +141,12 @@
                         block = null;
                     }
                     block = assignBlockNew(currentNode, block);
-                    if (currentNode.predecessors().size() == 0) {
+                    if (currentNode.predecessor() == null) {
                         // Either dead code or at a merge node => stop iteration.
                         break;
                     }
                     Node prev = currentNode;
-                    currentNode = currentNode.singlePredecessor();
+                    currentNode = currentNode.predecessor();
                     assert !currentNode.isDeleted() : prev + " " + currentNode;
                 }
             }
@@ -161,9 +162,9 @@
                     predBlock.addSuccessor(block);
                 }
             } else {
-                for (Node pred : n.predecessors()) {
-                    if (isFixed(pred)) {
-                        Block predBlock = nodeToBlock.get(pred);
+                if (n.predecessor() != null) {
+                    if (isFixed(n.predecessor())) {
+                        Block predBlock = nodeToBlock.get(n.predecessor());
                         predBlock.addSuccessor(block);
                     }
                 }
@@ -400,8 +401,8 @@
                     return false;
                 }
             }
-            for (Node pred : n.predecessors()) {
-                if (!checkNodesAbove(allowedBlocks, pred)) {
+            if (n.predecessor() != null) {
+                if (!checkNodesAbove(allowedBlocks, n.predecessor())) {
                     return false;
                 }
             }
@@ -444,7 +445,7 @@
             int idx = sortedInstructions.indexOf(b.lastNode());
             boolean canNotMove = false;
             for (int i = idx + 1; i < sortedInstructions.size(); i++) {
-                if (sortedInstructions.get(i).inputs().contains(b.lastNode())) {
+                if (sortedInstructions.get(i).inputContains(b.lastNode())) {
                     canNotMove = true;
                     break;
                 }
@@ -489,8 +490,8 @@
             }
         }
 
-        for (Node pred : i.predecessors()) {
-            addToSorting(b, pred, sortedInstructions, map);
+        if (i.predecessor() != null) {
+            addToSorting(b, i.predecessor(), sortedInstructions, map);
         }
 
         map.mark(i);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/BitMap2D.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/BitMap2D.java	Thu Jul 28 08:18:43 2011 +0200
@@ -23,6 +23,7 @@
 package com.oracle.max.graal.compiler.util;
 
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 
 /**
  * This class implements a two-dimensional bitmap.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java	Thu Jul 28 08:18:43 2011 +0200
@@ -31,7 +31,8 @@
 import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
-import com.oracle.max.graal.graph.NodeWorkList.*;
+import com.oracle.max.graal.graph.collections.*;
+import com.oracle.max.graal.graph.collections.NodeWorkList.*;
 
 public class GraphUtil {
 
@@ -86,6 +87,8 @@
     }
 
     private static <T> Collection<Merge> colorCFGDownToMerge(Node from, T color, NodeMap<T> colors) {
+        throw new UnsupportedOperationException();
+        /*
         //System.out.println("colorCFGDownToMerge(" + from + ", " + color + ", colors)");
         NodeFlood work = from.graph().createNodeFlood();
         Collection<Merge> merges = new LinkedList<Merge>();
@@ -124,7 +127,7 @@
             }
         }
         //System.out.println("return " + merges);
-        return merges;
+        return merges;*/
     }
 
     public static interface ColorSplitingLambda<T> {
@@ -138,6 +141,8 @@
 
     // TODO (gd) rework that code around Phi handling : too complicated
     public static <T> void splitFromColoring(NodeMap<T> coloring, ColorSplitingLambda<T> lambda) {
+        throw new UnsupportedOperationException();
+        /*
         Map<Node, T> internalColoring = new HashMap<Node, T>();
         NodeWorkList work = coloring.graph().createNodeWorkList();
         for (Entry<Node, T> entry : coloring.entries()) {
@@ -283,7 +288,7 @@
                                 }
                             }
                         }
-                        lambda.fixNode(node, null /*white*/);
+                        lambda.fixNode(node, null*/ /*white*/ /*);
                     }
                     if (node instanceof StateSplit) {
                         FrameState stateAfter = ((StateSplit) node).stateAfter();
@@ -341,6 +346,6 @@
             Map<String, Object> debug = new HashMap<String, Object>();
             debug.put("split", debugColoring);
             compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Split end!!", coloring.graph(), true, false, debug));
-        }
+        }*/
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Thu Jul 28 08:18:43 2011 +0200
@@ -34,6 +34,7 @@
 import com.oracle.max.graal.compiler.util.GraphUtil.ColoringLambda;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.ci.*;
 
 public class LoopUtil {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Thu Jul 28 08:18:43 2011 +0200
@@ -40,10 +40,6 @@
  */
 public final class FrameState extends Value implements FrameStateAccess {
 
-    private static final int INPUT_COUNT = 1;
-
-    private static final int INPUT_OUTER_FRAME_STATE = 0;
-
     protected final int localsSize;
 
     protected final int stackSize;
@@ -52,32 +48,30 @@
 
     private boolean rethrowException;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
     public static final int BEFORE_BCI = -2;
     public static final int AFTER_BCI = -3;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + localsSize + stackSize + locksSize;
+    @NodeInput
+    private FrameState outerFrameState;
+
+    @NodeInput
+    private final NodeInputList<Value> values;
+
+    @NodeInput
+    private final NodeInputList<Node> virtualObjectMappings;
+
+    public FrameState outerFrameState() {
+        return outerFrameState;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    public FrameState outerFrameState() {
-        return (FrameState) inputs().get(super.inputCount() + INPUT_OUTER_FRAME_STATE);
-    }
-
-    public FrameState setOuterFrameState(FrameState n) {
-        return (FrameState) inputs().set(super.inputCount() + INPUT_OUTER_FRAME_STATE, n);
+    public void setOuterFrameState(FrameState x) {
+        updateUsages(this.outerFrameState, x);
+        this.outerFrameState = x;
     }
 
     @Override
     public void setValueAt(int i, Value x) {
-        inputs().set(INPUT_COUNT + i, x);
+        values.set(i, x);
     }
 
     /**
@@ -97,12 +91,14 @@
      * @param lockSize number of locks
      */
     public FrameState(RiMethod method, int bci, int localsSize, int stackSize, int locksSize, boolean rethrowException, Graph graph) {
-        super(CiKind.Illegal, localsSize + stackSize + locksSize + INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
         this.method = method;
         this.bci = bci;
         this.localsSize = localsSize;
         this.stackSize = stackSize;
         this.locksSize = locksSize;
+        this.values = new NodeInputList<Value>(this, localsSize + stackSize + locksSize);
+        this.virtualObjectMappings = new NodeInputList<Node>(this);
         this.rethrowException = rethrowException;
         GraalMetrics.FrameStatesCreated++;
         GraalMetrics.FrameStateValuesCreated += localsSize + stackSize + locksSize;
@@ -131,19 +127,19 @@
 
     public void addVirtualObjectMapping(Node virtualObject) {
         assert virtualObject instanceof VirtualObjectField || virtualObject instanceof Phi : virtualObject;
-        variableInputs().add(virtualObject);
+        virtualObjectMappings.add(virtualObject);
     }
 
     public int virtualObjectMappingCount() {
-        return variableInputs().size();
+        return virtualObjectMappings.size();
     }
 
     public Node virtualObjectMappingAt(int i) {
-        return variableInputs().get(i);
+        return virtualObjectMappings.get(i);
     }
 
-    public List<Node> virtualObjectMappings() {
-        return variableInputs();
+    public Iterable<Node> virtualObjectMappings() {
+        return virtualObjectMappings;
     }
 
     /**
@@ -155,8 +151,8 @@
 
     public FrameState duplicate(int bci, boolean duplicateOuter) {
         FrameState other = new FrameState(method, bci, localsSize, stackSize, locksSize, rethrowException, graph());
-        other.inputs().setAll(inputs());
-        other.variableInputs().addAll(variableInputs());
+        other.values.setAll(values);
+        other.virtualObjectMappings.setAll(virtualObjectMappings);
         FrameState outerFrameState = outerFrameState();
         if (duplicateOuter && outerFrameState != null) {
             outerFrameState = outerFrameState.duplicate(outerFrameState.bci, duplicateOuter);
@@ -192,7 +188,7 @@
         for (int i = 0; i < locksSize; i++) {
             other.setValueAt(localsSize + other.stackSize + i, lockAt(i));
         }
-        other.variableInputs().addAll(variableInputs());
+        other.virtualObjectMappings.setAll(virtualObjectMappings);
         other.setOuterFrameState(outerFrameState());
         return other;
     }
@@ -382,7 +378,7 @@
      */
     public Value valueAt(int i) {
         assert i < (localsSize + stackSize + locksSize);
-        return (Value) inputs().get(INPUT_COUNT + i);
+        return values.get(i);
     }
 
     /**
@@ -598,7 +594,7 @@
                 for (VirtualObject obj : vobjs) {
                     TTY.println("+" + obj);
                 }
-                for (Node vobj : variableInputs()) {
+                for (Node vobj : virtualObjectMappings()) {
                     if (vobj instanceof VirtualObjectField) {
                         TTY.println("-" + ((VirtualObjectField) vobj).object());
                     } else {
--- a/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizerImpl.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizerImpl.java	Thu Jul 28 08:18:43 2011 +0200
@@ -28,6 +28,7 @@
 import com.oracle.max.graal.examples.intrinsics.*;
 import com.oracle.max.graal.extensions.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java	Thu Jul 28 08:18:43 2011 +0200
@@ -30,41 +30,32 @@
 
 
 public final class ArrayWriteBarrier extends WriteBarrier {
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_OBJECT = 0;
-    private static final int INPUT_LOCATION = 1;
 
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private Value object;
+    @NodeInput
+    private LocationNode location;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Value object() {
+        return object;
     }
 
-    /**
-     * The instruction that produces the object tested against null.
-     */
-     public Value object() {
-        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    public void setObject(Value x) {
+        updateUsages(this.object, x);
+        this.object = x;
     }
 
-    public void setObject(Value n) {
-        inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    public LocationNode location() {
+        return location;
     }
 
-    /**
-     * The instruction that produces the object tested against null.
-     */
-     public LocationNode location() {
-        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
-    }
-
-    public void setLocation(LocationNode n) {
-        inputs().set(super.inputCount() + INPUT_LOCATION, n);
+    public void setLocation(LocationNode x) {
+        updateUsages(location, x);
+        location = x;
     }
 
     public ArrayWriteBarrier(Value object, LocationNode index, Graph graph) {
-        super(INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(graph);
         this.setObject(object);
         this.setLocation(index);
     }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java	Thu Jul 28 08:18:43 2011 +0200
@@ -30,29 +30,21 @@
 
 
 public final class FieldWriteBarrier extends WriteBarrier {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_OBJECT = 0;
 
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private Value object;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Value object() {
+        return object;
     }
 
-    /**
-     * The instruction that produces the object tested against null.
-     */
-     public Value object() {
-        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
-    }
-
-    public void setObject(Value n) {
-        inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    public void setObject(Value x) {
+        updateUsages(object, x);
+        object = x;
     }
 
     public FieldWriteBarrier(Value object, Graph graph) {
-        super(INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(graph);
         this.setObject(object);
     }
 
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java	Mon Jul 25 12:12:10 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java	Thu Jul 28 08:18:43 2011 +0200
@@ -31,11 +31,9 @@
 
 
 public abstract class WriteBarrier extends FixedNodeWithNext {
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
 
-    public WriteBarrier(int inputCount, int successorCount, Graph graph) {
-        super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public WriteBarrier(Graph graph) {
+        super(CiKind.Illegal, graph);
     }