changeset 3492:e04e88087e98

Merga
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Fri, 05 Aug 2011 18:44:32 +0200
parents 2ae2861243b1 (current diff) 66e8bde93b6d (diff)
children faf60b7be40d
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.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/gen/LIRGenerator.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/ir/ArrayLength.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.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/GuardNode.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/InstanceOf.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NormalizeCompare.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.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/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/ConvertConditionalPhase.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/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/target/amd64/AMD64LIRAssembler.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.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java
diffstat 126 files changed, 1213 insertions(+), 1595 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Fri Aug 05 18:44:32 2011 +0200
@@ -230,27 +230,40 @@
     }
 
     private void emitLIR() {
-        if (GraalOptions.GenLIR) {
-            if (GraalOptions.Time) {
-                GraalTimers.LIR_CREATE.start();
-            }
+        try {
+            if (GraalOptions.GenLIR) {
+                if (GraalOptions.Time) {
+                    GraalTimers.LIR_CREATE.start();
+                }
 
-            initFrameMap(hir.maxLocks());
+                initFrameMap(hir.maxLocks());
+
+                lirGenerator = compiler.backend.newLIRGenerator(this);
 
-            lirGenerator = compiler.backend.newLIRGenerator(this);
+                for (LIRBlock b : hir.linearScanOrder()) {
+                    lirGenerator.doBlock(b);
+                }
 
-            for (LIRBlock b : hir.linearScanOrder()) {
-                lirGenerator.doBlock(b);
-            }
+                if (GraalOptions.Time) {
+                    GraalTimers.LIR_CREATE.stop();
+                }
+
+                if (GraalOptions.PrintLIR && !TTY.isSuppressed()) {
+                    LIRList.printLIR(hir.linearScanOrder());
+                }
 
-            if (GraalOptions.Time) {
-                GraalTimers.LIR_CREATE.stop();
+                new LinearScan(this, hir, lirGenerator, frameMap()).allocate();
+            }
+        } catch (AssertionError e) {
+            if (compiler.isObserved() && GraalOptions.PlotOnError) {
+                compiler.fireCompilationEvent(new CompilationEvent(this, "AssertionError in emitLIR", graph, true, false, true));
             }
-            if (GraalOptions.PrintLIR && !TTY.isSuppressed()) {
-                LIRList.printLIR(hir.linearScanOrder());
+            throw e;
+        } catch (RuntimeException e) {
+            if (compiler.isObserved() && GraalOptions.PlotOnError) {
+                compiler.fireCompilationEvent(new CompilationEvent(this, "RuntimeException in emitLIR", graph, true, false, true));
             }
-
-            new LinearScan(this, hir, lirGenerator, frameMap()).allocate();
+            throw e;
         }
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Fri Aug 05 18:44:32 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);
@@ -95,7 +95,7 @@
         }
 
         CiResult result = null;
-        TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
+        TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, CiUtil.format("%H.%n", method, false));
         GraalCompilation compilation = new GraalCompilation(this, method, osrBCI, stats);
         currentCompilation = compilation;
         try {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Fri Aug 05 18:44:32 2011 +0200
@@ -1333,7 +1333,7 @@
 
     }
 
-    boolean isSorted(Interval[] intervals) {
+    private boolean isSorted(Interval[] intervals) {
         int from = -1;
         for (Interval interval : intervals) {
             assert interval != null;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java	Fri Aug 05 18:44:32 2011 +0200
@@ -27,17 +27,17 @@
 
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.alloc.*;
-import com.oracle.max.graal.compiler.alloc.Interval.*;
+import com.oracle.max.graal.compiler.alloc.Interval.UsePosList;
 import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.*;
+import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFormatter;
 import com.oracle.max.graal.compiler.schedule.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
-import com.sun.cri.ci.CiAddress.*;
+import com.sun.cri.ci.CiAddress.Scale;
 import com.sun.cri.ri.*;
 
 /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Fri Aug 05 18:44:32 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
@@ -140,8 +141,15 @@
         List<Loop> loops = null;
         try {
             loops = LoopUtil.computeLoops(graph);
+            // loop.nodes() does some more calculations which may fail, so execute this here as well
+            if (loops != null) {
+                for (Loop loop : loops) {
+                    loop.nodes();
+                }
+            }
         } catch (Throwable t) {
             t.printStackTrace();
+            loops = null;
         }
 
         stream.println("  <nodes>");
@@ -319,7 +327,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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Fri Aug 05 18:44:32 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 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/PhiSimplifier.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Fri Aug 05 18:44:32 2011 +0200
@@ -292,6 +292,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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/PostOrderNodeIterator.java	Fri Aug 05 18:44:32 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/AbstractMemoryCheckpointNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractMemoryCheckpointNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,15 +30,18 @@
 
 public abstract class AbstractMemoryCheckpointNode extends StateSplit {
 
+    @NodeInput
+    private final NodeInputList<Node> mergedNodes = new NodeInputList<Node>(this);
+
     private static final int SUCCESSOR_COUNT = 0;
     private static final int INPUT_COUNT = 0;
 
     public AbstractMemoryCheckpointNode(Graph graph) {
-        this(CiKind.Illegal, 0, 0, graph);
+        this(CiKind.Illegal, graph);
     }
 
-    public AbstractMemoryCheckpointNode(CiKind result, int inputCount, int successorCount, Graph graph) {
-        super(result, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public AbstractMemoryCheckpointNode(CiKind result, Graph graph) {
+        super(result, graph);
     }
 
     @Override
@@ -48,7 +51,7 @@
         return debugProperties;
     }
 
-    public List<Node> mergedNodes() {
-        return variableInputs();
+    public NodeInputList<Node> mergedNodes() {
+        return mergedNodes;
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,30 +30,20 @@
 
 public abstract class AbstractVectorNode extends StateSplit {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_VECTOR = 0;
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private AbstractVectorNode vector;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public AbstractVectorNode vector() {
+        return vector;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public void setVector(AbstractVectorNode x) {
+        updateUsages(vector, x);
+        vector = x;
     }
 
-    public void setVector(AbstractVectorNode length) {
-        inputs().set(super.inputCount() + INPUT_VECTOR, length);
-    }
-
-    public AbstractVectorNode vector() {
-        return (AbstractVectorNode) inputs().get(super.inputCount() + INPUT_VECTOR);
-    }
-
-    public AbstractVectorNode(CiKind kind, int inputCount, int successorCount, AbstractVectorNode vector, Graph graph) {
-        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public AbstractVectorNode(CiKind kind, AbstractVectorNode vector, Graph graph) {
+        super(kind, graph);
         setVector(vector);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessArray.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessArray.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,42 +30,26 @@
  */
 public abstract class AccessArray extends StateSplit {
 
-    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;
     }
 
     /**
      * Creates a new AccessArray instruction.
      * @param kind the type of the result of this instruction
      * @param array the instruction that produces the array object value
-     * @param inputCount
-     * @param successorCount
      * @param graph
      */
-    public AccessArray(CiKind kind, Value array, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public AccessArray(CiKind kind, Value array, Graph graph) {
+        super(kind, graph);
         setArray(array);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessField.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessField.java	Fri Aug 05 18:44:32 2011 +0200
@@ -34,30 +34,16 @@
  */
 public abstract class AccessField 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 receiver object of this field access (for instance field accesses).
-     */
-     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;
     }
 
     protected final RiField field;
@@ -67,12 +53,10 @@
      * @param kind the result kind of the access
      * @param object the instruction producing the receiver object
      * @param field the compiler interface representation of the field
-     * @param inputCount
-     * @param successorCount
      * @param graph
      */
-    public AccessField(CiKind kind, Value object, RiField field, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public AccessField(CiKind kind, Value object, RiField field, Graph graph) {
+        super(kind, graph);
         this.field = field;
         setObject(object);
         assert field.isResolved();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessIndexed.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessIndexed.java	Fri Aug 05 18:44:32 2011 +0200
@@ -31,42 +31,28 @@
  */
 public abstract class AccessIndexed extends AccessArray {
 
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_INDEX = 0;
-    private static final int INPUT_LENGTH = 1;
-
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private Value index;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
+    @NodeInput
+    private Value length;
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public Value index() {
+        return index;
     }
 
-    /**
-     * The instruction producing the index into the array.
-     */
-     public Value index() {
-        return (Value) inputs().get(super.inputCount() + INPUT_INDEX);
+    public void setIndex(Value x) {
+        updateUsages(index, x);
+        index = x;
     }
 
-    public Value setIndex(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_INDEX, n);
+    public Value length() {
+        return length;
     }
 
-    /**
-     * The instruction that produces the length of the 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(length, x);
+        length = x;
     }
 
     private final CiKind elementType;
@@ -78,12 +64,10 @@
      * @param index the instruction producing the index
      * @param length the instruction producing the length (used in bounds check elimination?)
      * @param elementKind the type of the elements of the array
-     * @param inputCount
-     * @param successorCount
      * @param graph
      */
-    AccessIndexed(CiKind kind, Value array, Value index, Value length, CiKind elementKind, int inputCount, int successorCount, Graph graph) {
-        super(kind, array, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    AccessIndexed(CiKind kind, Value array, Value index, Value length, CiKind elementKind, Graph graph) {
+        super(kind, array, graph);
         setIndex(index);
         setLength(length);
         this.elementType = elementKind;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessMonitor.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessMonitor.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,42 +30,28 @@
  */
 public abstract class AccessMonitor extends AbstractMemoryCheckpointNode {
 
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_OBJECT = 0;
-    private static final int INPUT_LOCK_ADDRESS = 1;
-
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private Value object;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
+    @NodeInput
+    private Value lockAddress;
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public Value object() {
+        return object;
     }
 
-    /**
-     * The instruction producing the object locked or unlocked by this instruction.
-     */
-     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);
+    public Value lockAddress() {
+        return lockAddress;
     }
 
-    /**
-     * The instruction producing the address of the lock object.
-     */
-    public Value lockAddress() {
-        return (Value) inputs().get(super.inputCount() + INPUT_LOCK_ADDRESS);
-    }
-
-    public Value setLockAddress(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_LOCK_ADDRESS, n);
+    public void setLockAddress(Value x) {
+        updateUsages(lockAddress, x);
+        lockAddress = x;
     }
 
     /**
@@ -79,12 +65,10 @@
      * @param object the instruction producing the object
      * @param lockAddress the address of the on-stack lock object or {@code null} if the runtime does not place locks on the stack
      * @param lockNumber the number of the lock being acquired
-     * @param inputCount
-     * @param successorCount
      * @param graph
      */
-    public AccessMonitor(Value object, Value lockAddress, int lockNumber, int inputCount, int successorCount, Graph graph) {
-        super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public AccessMonitor(Value object, Value lockAddress, int lockNumber, Graph graph) {
+        super(CiKind.Illegal, graph);
         this.lockNumber = lockNumber;
         setObject(object);
         setLockAddress(lockAddress);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -22,64 +22,64 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
-import java.util.*;
-
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 
 
 public abstract class AccessNode extends AbstractMemoryCheckpointNode {
-    private static final int INPUT_COUNT = 3;
-    private static final int INPUT_NODE = 0;
-    private static final int INPUT_LOCATION = 1;
-    private static final int INPUT_GUARD = 2;
+
+    @NodeInput
+    private Value object;
 
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private GuardNode guard;
 
+    @NodeInput
     private LocationNode location;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
+    @NodeInput
+    private final NodeInputList<Node> dependencies = new NodeInputList<Node>(this);
 
     public Value object() {
-        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+        return object;
     }
 
-    public Value setObject(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_NODE, n);
+    public void setObject(Value x) {
+        updateUsages(object, x);
+        object = x;
     }
 
     public GuardNode guard() {
-        return (GuardNode) inputs().get(super.inputCount() + INPUT_GUARD);
+        return guard;
     }
 
-    public void setGuard(GuardNode n) {
-        inputs().set(super.inputCount() + INPUT_GUARD, n);
+    public void setGuard(GuardNode x) {
+        updateUsages(guard, x);
+        guard = x;
     }
 
     public LocationNode location() {
-        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
+        return location;
     }
 
-    public void setLocation(LocationNode n) {
-        inputs().set(super.inputCount() + INPUT_LOCATION, n);
+    public void setLocation(LocationNode x) {
+        updateUsages(location, x);
+        location = x;
     }
 
-    public AccessNode(CiKind kind, Value object, LocationNode location, int inputCount, int successorCount, Graph graph) {
-        super(kind, INPUT_COUNT + inputCount, SUCCESSOR_COUNT + successorCount, graph);
+    public AccessNode(CiKind kind, Value object, LocationNode location, Graph graph) {
+        super(kind, graph);
         setLocation(location);
         setObject(object);
     }
 
     public void addDependency(Node x) {
-        variableInputs().add(x);
+        dependencies.add(x);
     }
 
-    public List<Node> dependencies() {
-        return variableInputs();
+    public NodeInputList<Node> dependencies() {
+        return dependencies;
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessVectorNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessVectorNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -27,39 +27,36 @@
 
 
 public abstract class AccessVectorNode extends AbstractVectorNode {
-    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;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    @NodeInput
+    private LocationNode location;
+
+    @NodeInput
+    private final NodeInputList<Node> dependencies = new NodeInputList<Node>(this);
+
+    public Value object() {
+        return object;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    public void setObject(Value object) {
-        inputs().set(super.inputCount() + INPUT_OBJECT, object);
-    }
-
-    public Value object() {
-        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
-    }
-
-    public void setLocation(LocationNode object) {
-        inputs().set(super.inputCount() + INPUT_LOCATION, object);
+    public void setObject(Value x) {
+        updateUsages(object, x);
+        object = x;
     }
 
     public LocationNode location() {
-        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
+        return location;
     }
 
-    public AccessVectorNode(CiKind kind, int inputCount, int successorCount, AbstractVectorNode vector, Value object, LocationNode location, Graph graph) {
-        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, vector, graph);
+    public void setLocation(LocationNode x) {
+        updateUsages(location, x);
+        location = x;
+    }
+
+    public AccessVectorNode(CiKind kind, AbstractVectorNode vector, Value object, LocationNode location, Graph graph) {
+        super(kind, vector, graph);
         setObject(object);
         setLocation(location);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java	Fri Aug 05 18:44:32 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/Arithmetic.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Arithmetic.java	Fri Aug 05 18:44:32 2011 +0200
@@ -32,9 +32,6 @@
  */
 public abstract class Arithmetic extends Binary {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     private final boolean isStrictFP;
 
     /**
@@ -46,7 +43,7 @@
      * @param isStrictFP indicates this operation has strict rounding semantics
      */
     public Arithmetic(CiKind kind, int opcode, Value x, Value y, boolean isStrictFP, Graph graph) {
-        super(kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, opcode, x, y, graph);
         this.isStrictFP = isStrictFP;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java	Fri Aug 05 18:44:32 2011 +0200
@@ -38,30 +38,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;
     }
 
     /**
@@ -70,7 +56,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/Binary.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Binary.java	Fri Aug 05 18:44:32 2011 +0200
@@ -32,42 +32,28 @@
  */
 public abstract class Binary extends FloatingNode {
 
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_X = 0;
-    private static final int INPUT_Y = 1;
-
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private Value x;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
+    @NodeInput
+    private Value y;
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public Value x() {
+        return x;
     }
 
-    /**
-     * The first input to this instruction.
-     */
-     public Value x() {
-        return (Value) inputs().get(super.inputCount() + INPUT_X);
+    public void setX(Value x) {
+        updateUsages(this.x, x);
+        this.x = x;
     }
 
-    public Value setX(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_X, n);
+    public Value y() {
+        return y;
     }
 
-    /**
-     * The second input to this instruction.
-     */
-    public Value y() {
-        return (Value) inputs().get(super.inputCount() + INPUT_Y);
-    }
-
-    public Value setY(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_Y, n);
+    public void setY(Value x) {
+        updateUsages(y, x);
+        this.y = x;
     }
 
     /**
@@ -82,8 +68,8 @@
      * @param x the first input instruction
      * @param y the second input instruction
      */
-    public Binary(CiKind kind, int opcode, Value x, Value y, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public Binary(CiKind kind, int opcode, Value x, Value y, Graph graph) {
+        super(kind, graph);
         this.opcode = opcode;
         setX(x);
         setY(y);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -28,7 +28,7 @@
 
 public abstract class BooleanNode extends FloatingNode {
 
-    public BooleanNode(CiKind kind, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount, successorCount, graph);
+    public BooleanNode(CiKind kind, Graph graph) {
+        super(kind, graph);
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CastNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CastNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -29,24 +29,21 @@
 
 
 public final class CastNode extends FloatingNode {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_NODE = 0;
-
-    private static final int SUCCESSOR_COUNT = 0;
 
-    /**
-     * The instruction that produces the object tested against null.
-     */
+    @NodeInput
+    private Value value;
+
     public Value value() {
-        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+        return value;
     }
 
-    public void setValue(Value n) {
-        inputs().set(super.inputCount() + INPUT_NODE, n);
+    public void setValue(Value x) {
+        updateUsages(value, x);
+        value = x;
     }
 
     public CastNode(CiKind kind, Value n, Graph graph) {
-        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, graph);
         setValue(n);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java	Fri Aug 05 18:44:32 2011 +0200
@@ -35,9 +35,6 @@
  */
 public final class CheckCast extends TypeCheck {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     /**
      * Creates a new CheckCast instruction.
      * @param targetClass the class being cast to
@@ -45,7 +42,7 @@
      * @param graph
      */
     public CheckCast(Value targetClassInstruction, Value object, Graph graph) {
-        super(targetClassInstruction, object, CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(targetClassInstruction, object, CiKind.Object, graph);
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java	Fri Aug 05 18:44:32 2011 +0200
@@ -41,42 +41,28 @@
  */
 public final class Compare extends BooleanNode {
 
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_X = 0;
-    private static final int INPUT_Y = 1;
-
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private Value x;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
+    @NodeInput
+    private Value y;
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public Value x() {
+        return x;
     }
 
-    /**
-     * The instruction that produces the first input to this comparison.
-     */
-     public Value x() {
-        return (Value) inputs().get(super.inputCount() + INPUT_X);
+    public void setX(Value x) {
+        updateUsages(this.x, x);
+        this.x = x;
     }
 
-    public Value setX(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_X, n);
+    public Value y() {
+        return y;
     }
 
-    /**
-     * The instruction that produces the second input to this comparison.
-     */
-    public Value y() {
-        return (Value) inputs().get(super.inputCount() + INPUT_Y);
-    }
-
-    public Value setY(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_Y, n);
+    public void setY(Value x) {
+        updateUsages(y, x);
+        this.y = x;
     }
 
     private Condition condition;
@@ -90,7 +76,7 @@
      * @param graph
      */
     public Compare(Value x, Condition condition, Value y, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
         assert (x == null && y == null) || Util.archKindsEqual(x, y);
         this.condition = condition;
         setX(x);
@@ -231,8 +217,7 @@
                 }
             }
             boolean allUsagesNegate = true;
-            List<Node> usages = new ArrayList<Node>(compare.usages());
-            for (Node usage : usages) {
+            for (Node usage : compare.usages()) {
                 if (!(usage instanceof NegateBooleanNode)) {
                     allUsagesNegate = false;
                     break;
@@ -240,7 +225,7 @@
             }
             if (allUsagesNegate) {
                 compare.negate();
-                for (Node usage : usages) {
+                for (Node usage : compare.usages().snapshot()) {
                     usage.replaceAtUsages(compare);
                 }
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.java	Fri Aug 05 18:44:32 2011 +0200
@@ -40,37 +40,25 @@
  * by conditional expression elimination.
  */
 public class Conditional extends Binary {
-
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_CONDITION = 0;
-    private static final int INPUT_STATE = 1;
-
-    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;
-    }
+    @NodeInput private BooleanNode condition;
+    @NodeInput private FrameState stateDuring;
 
     public BooleanNode condition() {
-        return (BooleanNode) inputs().get(super.inputCount() + INPUT_CONDITION);
+        return condition;
     }
 
     public void setCondition(BooleanNode n) {
-        inputs().set(super.inputCount() + INPUT_CONDITION, n);
+        updateUsages(condition, n);
+        condition = n;
     }
 
     public FrameState stateDuring() {
-        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE);
+        return stateDuring;
     }
 
     public void setStateDuring(FrameState n) {
-        inputs().set(super.inputCount() + INPUT_STATE, n);
+        updateUsages(stateDuring, n);
+        stateDuring = n;
     }
 
     /**
@@ -83,13 +71,13 @@
      */
     public Conditional(BooleanNode condition, Value trueValue, Value falseValue, Graph graph) {
         // TODO: return the appropriate bytecode IF_ICMPEQ, etc
-        super(trueValue.kind.meet(falseValue.kind), Bytecodes.ILLEGAL, trueValue, falseValue, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(trueValue.kind.meet(falseValue.kind), Bytecodes.ILLEGAL, trueValue, falseValue, graph);
         setCondition(condition);
     }
 
     // for copying
     private Conditional(CiKind kind, Graph graph) {
-        super(kind, Bytecodes.ILLEGAL, null, null, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, Bytecodes.ILLEGAL, null, null, graph);
     }
 
     public Value trueValue() {
@@ -100,12 +88,12 @@
         return y();
     }
 
-    public Value setTrueValue(Value value) {
-        return setX(value);
+    public void setTrueValue(Value value) {
+        setX(value);
     }
 
-    public Value setFalseValue(Value value) {
-        return setY(value);
+    public void setFalseValue(Value value) {
+        setY(value);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java	Fri Aug 05 18:44:32 2011 +0200
@@ -35,9 +35,6 @@
  */
 public final class Constant extends BooleanNode {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     public final CiConstant value;
 
     /**
@@ -46,7 +43,7 @@
      * @param graph
      */
     public Constant(CiConstant value, Graph graph) {
-        super(value.kind.stackKind(), INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(value.kind.stackKind(), graph);
         this.value = value;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ControlSplit.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ControlSplit.java	Fri Aug 05 18:44:32 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/Convert.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Convert.java	Fri Aug 05 18:44:32 2011 +0200
@@ -33,30 +33,16 @@
  */
 public final class Convert extends FloatingNode {
 
-    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 which produces the input value to this instruction.
-     */
-     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;
     }
 
     /**
@@ -72,7 +58,7 @@
      * @param graph
      */
     public Convert(int opcode, Value value, CiKind kind, Graph graph) {
-        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, graph);
         this.opcode = opcode;
         setValue(value);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -33,17 +33,21 @@
 
 
 public final class CreateVectorNode extends AbstractVectorNode {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_LENGTH = 0;
-    private static final int SUCCESSOR_COUNT = 0;
+
+    @NodeInput
+    private Value length;
+
+    public Value length() {
+        return length;
+    }
+
+    public void setLength(Value x) {
+        updateUsages(length, x);
+        length = x;
+    }
 
     private boolean reversed;
 
-    public void setLength(Value length) {
-        assert length == null || length.kind == CiKind.Int;
-        inputs().set(super.inputCount() + INPUT_LENGTH, length);
-    }
-
     public boolean reversed() {
         return reversed;
     }
@@ -52,12 +56,8 @@
         reversed = r;
     }
 
-    public Value length() {
-        return (Value) inputs().get(super.inputCount() + INPUT_LENGTH);
-    }
-
     public CreateVectorNode(boolean reversed, Value length, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, null, graph);
+        super(CiKind.Illegal, null, graph);
         setLength(length);
         setReversed(reversed);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Fri Aug 05 18:44:32 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
@@ -59,16 +57,13 @@
             return null;
         } else {
             assert usages().size() == 1;
-            return (Merge) usages().get(0);
+            return (Merge) usages().iterator().next();
         }
     }
 
     @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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionObject.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Fri Aug 05 18:44:32 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;
@@ -34,8 +32,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);
@@ -43,7 +42,7 @@
     }
 
     public FixedGuard(Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
     }
 
     @Override
@@ -56,8 +55,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
@@ -80,16 +79,14 @@
         @Override
         public Node canonical(Node node, NotifyReProcess reProcess) {
             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");
@@ -99,7 +96,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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedNode.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedNodeWithNext.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatingNode.java	Fri Aug 05 18:44:32 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/GuardNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -31,33 +31,36 @@
 
 
 public final class GuardNode extends FloatingNode {
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_ANCHOR = 0;
-    private static final int INPUT_NODE = 1;
 
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private FixedNode anchor;
+
+    @NodeInput
+    private BooleanNode node;
 
     public FixedNode anchor() {
-        return (FixedNode) inputs().get(super.inputCount() + INPUT_ANCHOR);
+        return anchor;
     }
 
-    public void setAnchor(FixedNode anchor) {
-        inputs().set(super.inputCount() + INPUT_ANCHOR, anchor);
+    public void setAnchor(FixedNode x) {
+        updateUsages(anchor, x);
+        anchor = x;
     }
 
     /**
      * The instruction that produces the tested boolean value.
      */
     public BooleanNode node() {
-        return (BooleanNode) inputs().get(super.inputCount() + INPUT_NODE);
+        return node;
     }
 
-    public void setNode(BooleanNode n) {
-        inputs().set(super.inputCount() + INPUT_NODE, n);
+    public void setNode(BooleanNode x) {
+        updateUsages(node, x);
+        node = x;
     }
 
     public GuardNode(BooleanNode node, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
         setNode(node);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Fri Aug 05 18:44:32 2011 +0200
@@ -35,34 +35,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/InstanceOf.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java	Fri Aug 05 18:44:32 2011 +0200
@@ -36,9 +36,6 @@
  */
 public final class InstanceOf extends TypeCheck {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     private boolean nullIsTrue;
 
     /**
@@ -48,7 +45,7 @@
      * @param graph
      */
     public InstanceOf(Constant targetClassInstruction, Value object, boolean nullIsTrue, Graph graph) {
-        super(targetClassInstruction, object, CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(targetClassInstruction, object, CiKind.Illegal, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAddVectorNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAddVectorNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,20 +30,21 @@
 
 
 public final class IntegerAddVectorNode extends AbstractVectorNode {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_VALUE = 0;
-    private static final int SUCCESSOR_COUNT = 0;
+
+    @NodeInput
+    private Value value;
 
     public Value value() {
-        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+        return value;
     }
 
-    public void setValue(Value v) {
-        inputs().set(super.inputCount() + INPUT_VALUE, v);
+    public void setValue(Value x) {
+        updateUsages(value, x);
+        value = x;
     }
 
     public IntegerAddVectorNode(AbstractVectorNode vector, Value value, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, graph);
+        super(CiKind.Illegal, vector, graph);
         setValue(value);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Fri Aug 05 18:44:32 2011 +0200
@@ -36,18 +36,26 @@
  */
 public final class Invoke extends AbstractMemoryCheckpointNode implements ExceptionEdgeInstruction {
 
-    private final int argumentCount;
+    @NodeSuccessor
+    private FixedNode exceptionEdge;
+
+    @NodeInput
+    private final NodeInputList<Value> arguments;
 
-    private static final int SUCCESSOR_COUNT = 1;
-    private static final int SUCCESSOR_EXCEPTION_EDGE = 0;
+    @Override
+    public FixedNode exceptionEdge() {
+        return exceptionEdge;
+    }
+
+    public void setExceptionEdge(FixedNode x) {
+        updatePredecessors(exceptionEdge, x);
+        exceptionEdge = x;
+    }
+
+    private final int argumentCount;
 
     private boolean canInline = true;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + argumentCount;
-    }
-
     public boolean canInline() {
         return canInline;
     }
@@ -56,41 +64,8 @@
         canInline = b;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    public List<Value> arguments() {
-        return new AbstractList<Value>() {
-            @Override
-            public int size() {
-                return argumentCount;
-            }
-
-            @Override
-            public Value get(int index) {
-                return (Value) inputs().get(Invoke.super.inputCount() + index);
-            }
-
-            @Override
-            public Value set(int index, Value node) {
-                return (Value) inputs().set(Invoke.super.inputCount() + index, node);
-            }
-        };
-
-    }
-
-    /**
-     * The entry to the exception dispatch chain for this invoke.
-     */
-    @Override
-    public FixedNode exceptionEdge() {
-        return (FixedNode) successors().get(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE);
-    }
-
-    public FixedNode setExceptionEdge(FixedNode n) {
-        return (FixedNode) successors().set(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE, n);
+    public NodeInputList<Value> arguments() {
+        return arguments;
     }
 
     public final int opcode;
@@ -108,7 +83,8 @@
      * @param target the target method being called
      */
     public Invoke(int bci, int opcode, CiKind result, Value[] args, RiMethod target, RiType returnType, Graph graph) {
-        super(result, args.length, SUCCESSOR_COUNT, graph);
+        super(result, graph);
+        arguments = new NodeInputList<Value>(this, args.length);
         this.opcode = opcode;
         this.target = target;
         this.returnType = returnType;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java	Fri Aug 05 18:44:32 2011 +0200
@@ -36,30 +36,16 @@
  */
 public final class IsNonNull extends BooleanNode {
 
-    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 tested against null.
-     */
-     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;
     }
 
     /**
@@ -68,7 +54,7 @@
      * @param graph
      */
     public IsNonNull(Value object, Graph graph) {
-        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Object, graph);
         assert object == null || object.kind == CiKind.Object : object;
         setObject(object);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java	Fri Aug 05 18:44:32 2011 +0200
@@ -38,30 +38,16 @@
  */
 public final class IsType extends BooleanNode {
 
-    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 tested against null.
-     */
-     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;
     }
 
     private final RiType type;
@@ -72,7 +58,7 @@
      * @param graph
      */
     public IsType(Value object, RiType type, Graph graph) {
-        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Object, graph);
         assert type.isResolved();
         assert object == null || object.kind == CiKind.Object;
         this.type = type;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java	Fri Aug 05 18:44:32 2011 +0200
@@ -37,9 +37,6 @@
 public final class LoadField extends AccessField {
     private static final LoadFieldCanonicalizerOp CANONICALIZER = new LoadFieldCanonicalizerOp();
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     /**
      * Creates a new LoadField instance.
      * @param object the receiver object
@@ -50,7 +47,7 @@
      * @param isLoaded indicates if the class is loaded
      */
     public LoadField(Value object, RiField field, Graph graph) {
-        super(field.kind().stackKind(), object, field, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(field.kind().stackKind(), object, field, graph);
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadIndexed.java	Fri Aug 05 18:44:32 2011 +0200
@@ -34,9 +34,6 @@
  */
 public final class LoadIndexed extends AccessIndexed {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     /**
      * Creates a new LoadIndexed instruction.
      * @param array the instruction producing the array
@@ -46,7 +43,7 @@
      * @param graph
      */
     public LoadIndexed(Value array, Value index, Value length, CiKind elementKind, Graph graph) {
-        super(elementKind.stackKind(), array, index, length, elementKind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(elementKind.stackKind(), array, index, length, elementKind, graph);
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Local.java	Fri Aug 05 18:44:32 2011 +0200
@@ -35,37 +35,23 @@
  */
 public final class Local extends FloatingNode {
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_START = 0;
+    @NodeInput
+    private StartNode start;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public StartNode start() {
+        return start;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public void setStart(StartNode x) {
+        updateUsages(start, x);
+        start = x;
     }
 
-    /**
-     * The start node of the graph that this local belongs to. This is used for correctly scheduling the locals.
-     */
-     private StartNode start() {
-        return (StartNode) inputs().get(super.inputCount() + INPUT_START);
-    }
-
-     private void setStart(StartNode n) {
-         inputs().set(super.inputCount() + INPUT_START, n);
-     }
-
     private final int index;
     private RiType declaredType;
 
     public Local(CiKind kind, int javaIndex, Graph graph) {
-        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, graph);
         this.index = javaIndex;
         setStart(graph.start());
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,10 +30,20 @@
 
 
 public final class LocationNode extends FloatingNode {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_INDEX = 0;
-    private static final int SUCCESSOR_COUNT = 0;
+
+    @NodeInput
+    private Value index;
 
+    public Value index() {
+        return index;
+    }
+
+    public void setIndex(Value x) {
+        updateUsages(index, x);
+        index = x;
+    }
+
+    public static final Object UNSAFE_ACCESS_LOCATION = new Object();
     public static final Object FINAL_LOCATION = new Object();
 
     public static Object getArrayLocation(CiKind elementKind) {
@@ -41,6 +51,7 @@
     }
 
     private int displacement;
+    private boolean indexScalingEnabled = true;
     private CiKind valueKind;
     private Object locationIdentity;
 
@@ -48,12 +59,18 @@
         return displacement;
     }
 
-    public Value index() {
-        return (Value) inputs().get(super.inputCount() + INPUT_INDEX);
+    /**
+     * @return whether scaling of the index by the value kind's size is enabled (the default) or disabled.
+     */
+    public boolean indexScalingEnabled() {
+        return indexScalingEnabled;
     }
 
-    public void setIndex(Value index) {
-        inputs().set(super.inputCount() + INPUT_INDEX, index);
+    /**
+     * Enables or disables scaling of the index by the value kind's size. Has no effect if the index input is not used.
+     */
+    public void setIndexScalingEnabled(boolean enable) {
+        this.indexScalingEnabled = enable;
     }
 
     public static LocationNode create(Object identity, CiKind kind, int displacement, Graph graph) {
@@ -62,7 +79,7 @@
     }
 
     private LocationNode(Object identity, CiKind kind, int displacement, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Illegal, graph);
         this.displacement = displacement;
         this.valueKind = kind;
         this.locationIdentity = identity;
@@ -95,7 +112,9 @@
         Scale indexScale = Scale.Times1;
         if (this.index() != null) {
             indexValue = lirGenerator.load(this.index());
+            if (indexScalingEnabled) {
             indexScale = Scale.fromInt(valueKind.sizeInBytes(lirGenerator.target().wordSize));
+            }
         }
         return new CiAddress(valueKind, lirGenerator.load(object), indexValue, indexScale, displacement);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Logic.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Logic.java	Fri Aug 05 18:44:32 2011 +0200
@@ -31,9 +31,6 @@
  */
 public abstract class Logic extends Binary {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     /**
      * Constructs a new logic operation instruction.
      * @param opcode the opcode of the logic operation
@@ -41,7 +38,7 @@
      * @param y the second input into this instruction
      */
     public Logic(CiKind kind, int opcode, Value x, Value y, Graph graph) {
-        super(kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, opcode, x, y, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java	Fri Aug 05 18:44:32 2011 +0200
@@ -110,7 +110,7 @@
     }
 
     @Override
-    public List<Node> phiPredecessors() {
+    public Iterable<Node> phiPredecessors() {
         return Arrays.asList(new Node[]{this.forwardEdge(), this.loopEnd()});
     }
 
@@ -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/LoopCounter.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopCounter.java	Fri Aug 05 18:44:32 2011 +0200
@@ -29,55 +29,50 @@
 
 public final class LoopCounter extends FloatingNode {
 
-    private static final int INPUT_COUNT = 3;
-    private static final int INPUT_MERGE = 0;
-    private static final int INPUT_INIT = 1;
-    private static final int INPUT_STRIDE = 2;
+    @NodeInput
+    private Value init;
+
+    @NodeInput
+    private Value stride;
+
+    @NodeInput
+    private LoopBegin loopBegin;
+
+    public Value init() {
+        return init;
+    }
+
+    public void setInit(Value x) {
+        updateUsages(init, x);
+        init = x;
+    }
 
-    private static final int SUCCESSOR_COUNT = 0;
+    public Value stride() {
+        return stride;
+    }
+
+    public void setStride(Value x) {
+        updateUsages(stride, x);
+        stride = x;
+    }
+
+    public LoopBegin loopBegin() {
+        return loopBegin;
+    }
+
+    public void setLoopBegin(LoopBegin x) {
+        updateUsages(loopBegin, x);
+        loopBegin = x;
+    }
 
     public LoopCounter(CiKind kind, Value init, Value stride, LoopBegin loop, Graph graph) {
-        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, graph);
         setInit(init);
         setStride(stride);
         setLoopBegin(loop);
     }
 
     @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
-
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    public Value init() {
-        return (Value) inputs().get(super.inputCount() + INPUT_INIT);
-    }
-
-    public Value setInit(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_INIT, n);
-    }
-
-    public Value stride() {
-        return (Value) inputs().get(super.inputCount() + INPUT_STRIDE);
-    }
-
-    public Value setStride(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_STRIDE, n);
-    }
-
-    public LoopBegin loopBegin() {
-        return (LoopBegin) inputs().get(super.inputCount() + INPUT_MERGE);
-    }
-
-    public Value setLoopBegin(LoopBegin n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_MERGE, n);
-    }
-
-    @Override
     public void accept(ValueVisitor v) {
         // TODO Auto-generated method stub
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java	Fri Aug 05 18:44:32 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/MaterializeNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -27,9 +27,6 @@
 
 public final class MaterializeNode extends Conditional {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
 
     public MaterializeNode(BooleanNode value, Graph graph) {
         super(value, Constant.forInt(1, graph), Constant.forInt(0, graph), graph);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Fri Aug 05 18:44:32 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<Node> ends = new NodeInputList<Node>(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,40 +49,25 @@
         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);
     }
 
     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 (EndNode) ends.get(index);
     }
 
     @Override
@@ -312,9 +290,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) {
@@ -340,7 +318,7 @@
         return Util.filter(this.usages(), Phi.class);
     }
 
-    public List<Node> phiPredecessors() {
-        return Collections.unmodifiableList(variableInputs());
+    public Iterable<Node> phiPredecessors() {
+        return ends;
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorAddress.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorAddress.java	Fri Aug 05 18:44:32 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/MonitorEnter.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorEnter.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,15 +30,6 @@
  */
 public final class MonitorEnter extends AccessMonitor {
 
-    private static final int INPUT_COUNT = 0;
-
-    private static final int SUCCESSOR_COUNT = 1;
-
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
     /**
      * Creates a new MonitorEnter instruction.
      *
@@ -48,7 +39,7 @@
      * @param graph
      */
     public MonitorEnter(Value object, Value lockAddress, int lockNumber, Graph graph) {
-        super(object, lockAddress, lockNumber, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(object, lockAddress, lockNumber, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorExit.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MonitorExit.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,9 +30,6 @@
  */
 public final class MonitorExit extends AccessMonitor {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     /**
      * Creates a new MonitorExit instruction.
      *
@@ -42,7 +39,7 @@
      * @param graph
      */
     public MonitorExit(Value object, Value lockAddress, int lockNumber, Graph graph) {
-        super(object, lockAddress, lockNumber, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(object, lockAddress, lockNumber, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java	Fri Aug 05 18:44:32 2011 +0200
@@ -36,30 +36,16 @@
 public final class Negate extends FloatingNode {
     private static final NegateCanonicalizerOp CANONICALIZER = new NegateCanonicalizerOp();
 
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_X = 0;
+    @NodeInput
+    private Value x;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Value x() {
+        return x;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction producing input to this instruction.
-     */
-     public Value x() {
-        return (Value) inputs().get(super.inputCount() + INPUT_X);
-    }
-
-    public Value setX(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_X, n);
+    public void setX(Value x) {
+        updateUsages(this.x, x);
+        this.x = x;
     }
 
     /**
@@ -67,13 +53,13 @@
      * @param x the instruction producing the value that is input to this instruction
      */
     public Negate(Value x, Graph graph) {
-        super(x.kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(x.kind, graph);
         setX(x);
     }
 
     // for copying
     private Negate(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/NegateBooleanNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -29,34 +29,21 @@
 import com.sun.cri.ci.*;
 
 public final class NegateBooleanNode extends BooleanNode {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_NODE = 0;
 
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private BooleanNode value;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public BooleanNode value() {
+        return value;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction that produces the array object.
-     */
-     public BooleanNode value() {
-        return (BooleanNode) inputs().get(super.inputCount() + INPUT_NODE);
-    }
-
-    public BooleanNode setValue(BooleanNode n) {
-        return (BooleanNode) inputs().set(super.inputCount() + INPUT_NODE, n);
+    public void setValue(BooleanNode x) {
+        updateUsages(value, x);
+        value = x;
     }
 
     public NegateBooleanNode(BooleanNode value, Graph graph) {
-        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Int, graph);
         setValue(value);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewMultiArray.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewObjectArray.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewTypeArray.java	Fri Aug 05 18:44:32 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/NormalizeCompare.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NormalizeCompare.java	Fri Aug 05 18:44:32 2011 +0200
@@ -34,9 +34,6 @@
  */
 public final class NormalizeCompare extends Binary {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     /**
      * Creates a new compare operation.
      * @param opcode the bytecode opcode
@@ -45,7 +42,7 @@
      * @param y the second input
      */
     public NormalizeCompare(int opcode, CiKind kind, Value x, Value y, Graph graph) {
-        super(kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, opcode, x, y, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Fri Aug 05 18:44:32 2011 +0200
@@ -38,35 +38,19 @@
  */
 public final class Phi extends FloatingNode {
 
-    private static final int DEFAULT_MAX_VALUES = 2;
-
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_MERGE = 0;
+    @NodeInput
+    private Merge merge;
 
-    private static final int SUCCESSOR_COUNT = 0;
-
-    private final PhiType type;
+    @NodeInput
+    private final NodeInputList<Value> values = new NodeInputList<Value>(this);
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Merge merge() {
+        return merge;
     }
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The merge node for this phi.
-     */
-    public Merge merge() {
-        return (Merge) inputs().get(super.inputCount() + INPUT_MERGE);
-    }
-
-    public void setMerge(Merge n) {
-        assert n != null;
-        inputs().set(super.inputCount() + INPUT_MERGE, n);
+    public void setMerge(Merge x) {
+        updateUsages(merge, x);
+        merge = x;
     }
 
     public static enum PhiType {
@@ -75,14 +59,16 @@
         Virtual         // phis used for VirtualObjectField merges
     }
 
+    private final PhiType type;
+
     public Phi(CiKind kind, Merge merge, PhiType type, Graph graph) {
-        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, graph);
         this.type = type;
         setMerge(merge);
     }
 
     private Phi(CiKind kind, PhiType type, Graph graph) {
-        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, graph);
         this.type = type;
     }
 
@@ -104,11 +90,11 @@
      * @return the instruction that produced the value in the i'th predecessor
      */
     public Value valueAt(int i) {
-        return (Value) variableInputs().get(i);
+        return values.get(i);
     }
 
     public void setValueAt(int i, Value x) {
-        inputs().set(INPUT_COUNT + i, x);
+        values.set(i, x);
     }
 
     /**
@@ -116,7 +102,7 @@
      * @return the number of inputs in this phi
      */
     public int valueCount() {
-        return variableInputs().size();
+        return values.size();
     }
 
     @Override
@@ -152,12 +138,12 @@
         }
     }
 
-    public void addInput(Node y) {
-        variableInputs().add(y);
+    public void addInput(Value x) {
+        values.add(x);
     }
 
     public void removeInput(int index) {
-        variableInputs().remove(index);
+        values.remove(index);
     }
 
     @Override
@@ -201,18 +187,12 @@
             }
             Node end0 = merge.endAt(0);
             Node end1 = merge.endAt(1);
-            if (end0.predecessors().size() != 1 || end1.predecessors().size() != 1) {
-                return phiNode;
-            }
-            Node endPred0 = end0.predecessors().get(0);
-            Node endPred1 = end1.predecessors().get(0);
+            Node endPred0 = end0.predecessor();
+            Node endPred1 = end1.predecessor();
             if (endPred0 != endPred1 || !(endPred0 instanceof If)) {
                 return phiNode;
             }
             If ifNode = (If) endPred0;
-            if (ifNode.predecessors().size() != 1) {
-                return phiNode;
-            }
             boolean inverted = ifNode.trueSuccessor() == end1;
             Value trueValue = phiNode.valueAt(inverted ? 1 : 0);
             Value falseValue = phiNode.valueAt(inverted ? 0 : 1);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Placeholder.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Placeholder.java	Fri Aug 05 18:44:32 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/ReadNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -28,12 +28,9 @@
 
 
 public final class ReadNode extends AccessNode {
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
 
     public ReadNode(CiKind kind, Value object, LocationNode location, Graph graph) {
-        super(kind, object, location, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, object, location, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadVectorNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadVectorNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,11 +30,9 @@
 
 
 public final class ReadVectorNode extends AccessVectorNode {
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
 
     public ReadVectorNode(AbstractVectorNode vector, Value object, LocationNode location, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, object, location, graph);
+        super(CiKind.Illegal, vector, object, location, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Fri Aug 05 18:44:32 2011 +0200
@@ -36,34 +36,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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Return.java	Fri Aug 05 18:44:32 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/Shift.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Shift.java	Fri Aug 05 18:44:32 2011 +0200
@@ -31,9 +31,6 @@
  */
 public abstract class Shift extends Binary {
 
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
-
     /**
      * Creates a new shift operation.
      * @param opcode the opcode of the shift
@@ -41,7 +38,7 @@
      * @param s the second input value
      */
     public Shift(CiKind kind, int opcode, Value x, Value s, Graph graph) {
-        super(kind, opcode, x, s, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, opcode, x, s, graph);
         assert x == null || x.kind == kind;
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Fri Aug 05 18:44:32 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/StoreField.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreField.java	Fri Aug 05 18:44:32 2011 +0200
@@ -34,30 +34,16 @@
  */
 public final class StoreField extends AccessField {
 
-    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 value that is written to the field.
-     */
-     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;
     }
 
     /**
@@ -69,7 +55,7 @@
      * @param graph
      */
     public StoreField(Value object, RiField field, Value value, Graph graph) {
-        super(CiKind.Void, object, field, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Void, object, field, graph);
         setValue(value);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreIndexed.java	Fri Aug 05 18:44:32 2011 +0200
@@ -33,30 +33,16 @@
  */
 public final class StoreIndexed extends AccessIndexed {
 
-    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 produces the value that is to be stored into the array.
-     */
-     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;
     }
 
     /**
@@ -70,7 +56,7 @@
      * @param graph
      */
     public StoreIndexed(Value array, Value index, Value length, CiKind elementKind, Value value, Graph graph) {
-        super(CiKind.Void, array, index, length, elementKind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Void, array, index, length, elementKind, graph);
         setValue(value);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Switch.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Switch.java	Fri Aug 05 18:44:32 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/TypeCheck.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java	Fri Aug 05 18:44:32 2011 +0200
@@ -31,45 +31,30 @@
  */
 public abstract class TypeCheck extends BooleanNode {
 
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_OBJECT = 0;
-    private static final int INPUT_TARGET_CLASS_INSTRUCTION = 1;
-
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private Value object;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
+    @NodeInput
+    private Value targetClassInstruction;
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
+    public Value object() {
+        return object;
     }
 
-    /**
-     * The instruction which produces the object input.
-     */
-     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;
     }
 
-    /**
-     * The instruction that loads the target class object that is used by this checkcast.
-     */
-     public Value targetClassInstruction() {
-        return (Value) inputs().get(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION);
+    public Value targetClassInstruction() {
+        return targetClassInstruction;
     }
 
-    private void setTargetClassInstruction(Value n) {
-        inputs().set(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION, n);
+    public void setTargetClassInstruction(Value x) {
+        updateUsages(targetClassInstruction, x);
+        targetClassInstruction = x;
     }
 
-
     /**
      * Gets the target class, i.e. the class being cast to, or the class being tested against.
      * @return the target class
@@ -83,12 +68,10 @@
      * @param targetClass the class which is being casted to or checked against
      * @param object the instruction which produces the object
      * @param kind the result type of this instruction
-     * @param inputCount
-     * @param successorCount
      * @param graph
      */
-    public TypeCheck(Value targetClassInstruction, Value object, CiKind kind, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public TypeCheck(Value targetClassInstruction, Value object, CiKind kind, Graph graph) {
+        super(kind, graph);
         setObject(object);
         setTargetClassInstruction(targetClassInstruction);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Unwind.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Unwind.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueAnchor.java	Fri Aug 05 18:44:32 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/ir/VirtualObject.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObject.java	Fri Aug 05 18:44:32 2011 +0200
@@ -33,25 +33,11 @@
 
 public class VirtualObject extends FloatingNode {
 
-    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;
-    }
-
     private EscapeField[] fields;
     private RiType type;
 
     public VirtualObject(RiType type, EscapeField[] fields, Graph graph) {
-        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Int, graph);
         this.type = type;
         this.fields = fields;
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObjectField.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/VirtualObjectField.java	Fri Aug 05 18:44:32 2011 +0200
@@ -31,54 +31,40 @@
 
 public class VirtualObjectField extends FloatingNode {
 
-    private static final int INPUT_COUNT = 3;
-    private static final int INPUT_OBJECT = 0;
-    private static final int INPUT_LAST_STATE = 1;
-    private static final int INPUT_INPUT = 2;
+    @NodeInput
+    private VirtualObject object;
 
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private FloatingNode lastState;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
+    @NodeInput
+    private Value input;
 
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The instruction that specifies the virtual object instance.
-     */
-     public VirtualObject object() {
-        return (VirtualObject) inputs().get(super.inputCount() + INPUT_OBJECT);
+    public VirtualObject object() {
+        return object;
     }
 
-    private VirtualObject setObject(VirtualObject n) {
-        return (VirtualObject) inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    public void setObject(VirtualObject x) {
+        updateUsages(object, x);
+        object = x;
     }
 
-    /**
-     * The instruction that specifies the old state of the virtual object.
-     */
-     public FloatingNode lastState() {
-        return (FloatingNode) inputs().get(super.inputCount() + INPUT_LAST_STATE);
+    public FloatingNode lastState() {
+        return lastState;
     }
 
-    private FloatingNode setLastState(FloatingNode n) {
-        return (FloatingNode) inputs().set(super.inputCount() + INPUT_LAST_STATE, n);
+    public void setLastState(FloatingNode x) {
+        updateUsages(lastState, x);
+        lastState = x;
     }
 
-    /**
-     * The instruction that contains the new state of the specified field.
-     */
-     public Value input() {
-        return (Value) inputs().get(super.inputCount() + INPUT_INPUT);
+    public Value input() {
+        return input;
     }
 
-    public Value setInput(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_INPUT, n);
+    public void setInput(Value x) {
+        updateUsages(input, x);
+        input = x;
     }
 
     private int index;
@@ -89,7 +75,7 @@
      * @param newFrameState the state after executing this instruction
      */
     public VirtualObjectField(VirtualObject object, FloatingNode lastState, Value input, int index, Graph graph) {
-        super(CiKind.Int, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Int, graph);
         this.index = index;
         setObject(object);
         setLastState(lastState);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteMemoryCheckpointNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteMemoryCheckpointNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -29,15 +29,12 @@
 
 public final class WriteMemoryCheckpointNode extends AbstractMemoryCheckpointNode {
 
-    private static final int SUCCESSOR_COUNT = 0;
-    private static final int INPUT_COUNT = 0;
-
     public WriteMemoryCheckpointNode(Graph graph) {
-        this(CiKind.Illegal, 0, 0, graph);
+        this(CiKind.Illegal, graph);
     }
 
-    public WriteMemoryCheckpointNode(CiKind result, int inputCount, int successorCount, Graph graph) {
-        super(result, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+    public WriteMemoryCheckpointNode(CiKind result, Graph graph) {
+        super(result, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -28,25 +28,21 @@
 
 
 public final class WriteNode extends AccessNode {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_VALUE = 0;
-    private static final int SUCCESSOR_COUNT = 0;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    @NodeInput
+    private Value value;
+
+    public Value value() {
+        return value;
     }
 
-    public Value value() {
-        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
-    }
-
-    public void setValue(Value v) {
-        inputs().set(super.inputCount() + INPUT_VALUE, v);
+    public void setValue(Value x) {
+        updateUsages(value, x);
+        value = x;
     }
 
     public WriteNode(CiKind kind, Value object, Value value, LocationNode location, Graph graph) {
-        super(kind, object, location, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, object, location, graph);
         setValue(value);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteVectorNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteVectorNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -31,20 +31,21 @@
 
 
 public final class WriteVectorNode extends AccessVectorNode {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_VALUES = 0;
-    private static final int SUCCESSOR_COUNT = 0;
 
-    public void setValues(AbstractVectorNode length) {
-        inputs().set(super.inputCount() + INPUT_VALUES, length);
+    @NodeInput
+    private AbstractVectorNode values;
+
+    public AbstractVectorNode values() {
+        return values;
     }
 
-    public AbstractVectorNode values() {
-        return (AbstractVectorNode) inputs().get(super.inputCount() + INPUT_VALUES);
+    public void setValues(AbstractVectorNode x) {
+        updateUsages(values, x);
+        values = x;
     }
 
     public WriteVectorNode(AbstractVectorNode vector, Value object, LocationNode location, AbstractVectorNode values, Graph graph) {
-        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, object, location, graph);
+        super(CiKind.Illegal, vector, object, location, graph);
         setValues(values);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Fri Aug 05 18:44:32 2011 +0200
@@ -27,7 +27,8 @@
 import java.util.*;
 
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.lir.LIROperand.*;
+import com.oracle.max.graal.compiler.lir.LIROperand.LIRAddressOperand;
+import com.oracle.max.graal.compiler.lir.LIROperand.LIRVariableOperand;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ComputeProbabilityPhase.java	Fri Aug 05 18:44:32 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/ConvertConditionalPhase.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ConvertConditionalPhase.java	Fri Aug 05 18:44:32 2011 +0200
@@ -99,27 +99,31 @@
                     prev = (Merge) firstNode;
                 } else if (firstNode instanceof EndNode) {
                     EndNode end = (EndNode) firstNode;
-                    Node pred = end.singlePredecessor();
+                    Node pred = end.predecessor();
                     Anchor anchor = new Anchor(graph);
-                    pred.successors().replace(end, anchor);
+                    pred.replaceFirstSuccessor(end, anchor);
                     anchor.setNext(end);
                     prev = anchor;
                 } else if (firstNode instanceof StartNode) {
                     StartNode start = (StartNode) firstNode;
                     Anchor anchor = new Anchor(graph);
-                    anchor.setNext((FixedNode) start.next());
+                    Node next = start.next();
+                    start.setNext(null);
+                    anchor.setNext((FixedNode) next);
                     start.setNext(anchor);
                     prev = anchor;
                 } else if (firstNode instanceof If) {
-                    Node pred = firstNode.singlePredecessor();
+                    Node pred = firstNode.predecessor();
                     Anchor anchor = new Anchor(graph);
-                    pred.successors().replace(firstNode, anchor);
+                    pred.replaceFirstSuccessor(firstNode, anchor);
                     anchor.setNext((If) firstNode);
                     prev = anchor;
                 } else {
                     prev = (FixedNodeWithNext) firstNode;
                 }
-                merge.setNext(prev.next());
+                FixedNode next = prev.next();
+                prev.setNext(null);
+                merge.setNext(next);
                 prev.setNext(ifNode);
                 conditional.replaceAndDelete(phi);
             } else {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Fri Aug 05 18:44:32 2011 +0200
@@ -22,13 +22,12 @@
  */
 package com.oracle.max.graal.compiler.phases;
 
-import java.util.*;
-
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 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 +44,6 @@
         iterateSuccessors();
         disconnectCFGNodes();
         iterateInputs();
-        disconnectNodes();
         deleteNodes();
 
         // remove chained Merges
@@ -95,13 +93,17 @@
                     LoopBegin loop = ((LoopEnd) node).loopBegin();
                     if (flood.isMarked(loop)) {
                         if (GraalOptions.TraceDeadCodeElimination) {
-                            TTY.println("Building loop begin node back: " + loop);
+                            TTY.println("Removing loop with unreachable end: " + loop);
                         }
                         ((LoopEnd) node).setLoopBegin(null);
                         EndNode endNode = loop.endAt(0);
-                        assert endNode.predecessors().size() == 1 : endNode.predecessors().size();
+                        assert endNode.predecessor() != null;
                         replacePhis(loop);
-                        endNode.replaceAndDelete(loop.next());
+                        loop.removeEnd(endNode);
+
+                        FixedNode next = loop.next();
+                        loop.setNext(null);
+                        endNode.replaceAndDelete(next);
                         loop.delete();
                     }
                 }
@@ -110,7 +112,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 +121,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 +149,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/DuplicationPhase.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DuplicationPhase.java	Fri Aug 05 18:44:32 2011 +0200
@@ -44,7 +44,12 @@
         // Delete nodes in original graph.
         for (Node n : graph.getNodes()) {
             if (n != graph.start()) {
-                n.forceDelete();
+                n.clearEdges();
+            }
+        }
+        for (Node n : graph.getNodes()) {
+            if (n != graph.start()) {
+                n.delete();
             }
         }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GlobalValueNumberingPhase.java	Fri Aug 05 18:44:32 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Fri Aug 05 18:44:32 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.*;
@@ -119,8 +120,6 @@
         super(inline ? "BuildInlineGraph" : "BuildGraph");
         this.compilation = compilation;
 
-        setDetailedName(getName() + " " + method.holder().name() + "." + method.name() + method.signature().asString());
-
         this.runtime = compilation.runtime;
         this.method = method;
         this.stats = compilation.stats;
@@ -139,6 +138,11 @@
         build();
     }
 
+    @Override
+    protected String getDetailedName() {
+        return getName() + " " + method.holder().name() + "." + method.name() + method.signature().asString();
+    }
+
     /**
      * Builds the graph for a the specified {@code IRScope}.
      *
@@ -206,7 +210,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 +288,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 +313,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);
@@ -973,9 +976,9 @@
             Invoke invoke = new Invoke(bci(), opcode, resultType.stackKind(), args, target, target.signature().returnType(method.holder()), graph);
             Value result = appendWithBCI(invoke);
             invoke.setExceptionEdge(handleException(null, bci()));
-            if (invoke.exceptionEdge() == null) {
-                TTY.println("no exception edge" + unwindHandler);
-            }
+//            if (invoke.exceptionEdge() == null) {
+//                TTY.println("no exception edge" + unwindHandler);
+//            }
             frameState.pushReturn(resultType, result);
         }
     }
@@ -1116,14 +1119,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;
                 }
 
@@ -1136,6 +1139,7 @@
                 If ifNode = (If) cur;
                 if (ifNode.falseSuccessor() == prev) {
                     FixedNode successor = ifNode.trueSuccessor();
+                    ifNode.setTrueSuccessor(null);
                     BooleanNode condition = ifNode.compare();
                     FixedGuard fixedGuard = new FixedGuard(condition, graph);
                     fixedGuard.setNext(successor);
@@ -1163,7 +1167,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;
@@ -1204,7 +1208,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;
         }
@@ -1285,7 +1289,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 (;;) {
@@ -1303,7 +1307,9 @@
                     loopEnd.delete();
                     Merge merge = new Merge(graph);
                     merge.addEnd(begin.forwardEdge());
-                    merge.setNext(begin.next());
+                    FixedNode next = begin.next();
+                    begin.setNext(null);
+                    merge.setNext(next);
                     merge.setStateAfter(begin.stateAfter());
                     begin.replaceAndDelete(merge);
                 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Fri Aug 05 18:44:32 2011 +0200
@@ -196,8 +196,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) {
@@ -258,7 +258,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));
             }
@@ -478,7 +478,7 @@
             }
         }
 
-        invoke.inputs().clearAll();
+        invoke.clearInputs();
 
         HashMap<Node, Node> replacements = new HashMap<Node, Node>();
         ArrayList<Node> nodes = new ArrayList<Node>();
@@ -507,8 +507,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);
@@ -555,20 +555,21 @@
         }
 
         if (pred instanceof Placeholder) {
-            pred.replaceAndDelete(((Placeholder) pred).next());
+            FixedNode next = ((Placeholder) pred).next();
+            ((Placeholder) pred).setNext(null);
+            pred.replaceAndDelete(next);
         }
 
         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);
@@ -576,16 +577,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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Fri Aug 05 18:44:32 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.*;
 
 
@@ -134,13 +135,12 @@
     private List<LoopCounter> findLoopCounters(LoopBegin loopBegin, NodeBitMap loopNodes) {
         LoopEnd loopEnd = loopBegin.loopEnd();
         FrameState loopEndState = null;
-        Node loopEndPred = loopEnd.singlePredecessor();
+        Node loopEndPred = loopEnd.predecessor();
         if (loopEndPred instanceof Merge) {
             loopEndState = ((Merge) loopEndPred).stateAfter();
         }
-        List<Node> usages = new ArrayList<Node>(loopBegin.usages());
         List<LoopCounter> counters = new LinkedList<LoopCounter>();
-        for (Node usage : usages) {
+        for (Node usage : loopBegin.usages().snapshot()) {
             if (usage instanceof Phi) {
                 Phi phi = (Phi) usage;
                 if (phi.valueCount() == 2) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/MemoryPhase.java	Fri Aug 05 18:44:32 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 {
@@ -72,8 +73,9 @@
             StartNode startNode = b.firstNode().graph().start();
             if (b.firstNode() == startNode) {
                 WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(startNode.graph());
-                checkpoint.setNext((FixedNode) startNode.next());
+                FixedNode next = (FixedNode) startNode.next();
                 startNode.setNext(checkpoint);
+                checkpoint.setNext(next);
                 mergeForWrite = checkpoint;
                 mergeForRead = checkpoint;
             }
@@ -149,7 +151,7 @@
             Merge m = (Merge) block.firstNode();
             if (original instanceof Phi && ((Phi) original).merge() == m) {
                 Phi phi = (Phi) original;
-                phi.addInput(newValue);
+                phi.addInput((Value) newValue);
                 if (GraalOptions.TraceMemoryMaps) {
                     TTY.println("Add new input to phi " + original.id());
                 }
@@ -158,9 +160,9 @@
             } else {
                 Phi phi = new Phi(CiKind.Illegal, m, PhiType.Memory, m.graph());
                 for (int i = 0; i < mergeOperationCount + 1; ++i) {
-                    phi.addInput(original);
+                    phi.addInput((Value) original);
                 }
-                phi.addInput(newValue);
+                phi.addInput((Value) newValue);
                 if (GraalOptions.TraceMemoryMaps) {
                     TTY.println("Creating new phi " + phi.id());
                 }
@@ -232,21 +234,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);
             }
         }
     }
@@ -291,16 +292,18 @@
         for (final Node n : b.getInstructions()) {
             if (n instanceof ReadNode) {
                 ReadNode readNode = (ReadNode) n;
-                readNode.replaceAtPredecessors(readNode.next());
+                FixedNode next = readNode.next();
                 readNode.setNext(null);
+                readNode.replaceAtPredecessors(next);
                 map.registerRead(readNode);
             } else if (n instanceof WriteNode) {
                 WriteNode writeNode = (WriteNode) n;
                 WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(writeNode.graph());
                 checkpoint.setStateAfter(writeNode.stateAfter());
                 writeNode.setStateAfter(null);
-                checkpoint.setNext(writeNode.next());
+                FixedNode next = writeNode.next();
                 writeNode.setNext(null);
+                checkpoint.setNext(next);
                 writeNode.replaceAtPredecessors(checkpoint);
                 map.registerWrite(writeNode);
                 map.createWriteMemoryMerge(checkpoint);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Fri Aug 05 18:44:32 2011 +0200
@@ -25,19 +25,17 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.schedule.*;
-import com.oracle.max.graal.graph.Graph;
+import com.oracle.max.graal.graph.*;
 
 public abstract class Phase {
 
     private final String name;
-    private String detailedName;
     private static final ThreadLocal<Phase> currentPhase = new ThreadLocal<Phase>();
     private final boolean shouldVerify;
 
     protected Phase() {
         this.name = this.getClass().getSimpleName();
         this.shouldVerify = GraalOptions.Verify;
-        this.detailedName = name;
     }
 
     protected Phase(String name) {
@@ -47,11 +45,10 @@
     protected Phase(String name, boolean shouldVerify) {
         this.name = name;
         this.shouldVerify = shouldVerify;
-        this.detailedName = name;
     }
 
-    protected void setDetailedName(String detailedName) {
-        this.detailedName = detailedName;
+    protected String getDetailedName() {
+        return getName();
     }
 
     public final void apply(Graph graph) {
@@ -78,17 +75,16 @@
         } catch (AssertionError t) {
             GraalCompilation compilation = GraalCompilation.compilation();
             if (compilation.compiler.isObserved() && plotOnError) {
-                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + detailedName, graph, true, false, true));
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "AssertionError in " + getDetailedName(), graph, true, false, true));
             }
             throw t;
         } catch (RuntimeException t) {
             GraalCompilation compilation = GraalCompilation.compilation();
             if (compilation.compiler.isObserved() && plotOnError) {
-                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + detailedName, graph, true, false, true));
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in " + getDetailedName(), graph, true, false, true));
             }
             throw t;
         }
-        //System.out.println("Finished Phase " + getName());
         if (GraalOptions.Time) {
             GraalTimers.get(getName()).stop();
             if (oldCurrentPhase != null) {
@@ -105,7 +101,7 @@
         }
         GraalCompilation compilation = GraalCompilation.compilation();
         if (compilation.compiler.isObserved() && this.getClass() != IdentifyBlocksPhase.class && (plot || GraalOptions.PlotVerbose)) {
-            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + detailedName, graph, true, false));
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + getDetailedName(), graph, true, false));
         }
 
         assert !shouldVerify || graph.verify();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Fri Aug 05 18:44:32 2011 +0200
@@ -112,8 +112,9 @@
                     this.anchor = (Anchor) start.next();
                 } else {
                     Anchor a = new Anchor(firstNode.graph());
-                    a.setNext((FixedNode) firstNode.graph().start().next());
+                    FixedNode oldStart = (FixedNode) firstNode.graph().start().next();
                     firstNode.graph().start().setNext(a);
+                    a.setNext(oldStart);
                     this.anchor = a;
                 }
             } else if (firstNode instanceof Merge || firstNode instanceof ExceptionObject) {
@@ -122,17 +123,17 @@
                     this.anchor = (Anchor) fixedNode.next();
                 } else {
                     Anchor a = new Anchor(firstNode.graph());
-                    a.setNext(fixedNode.next());
+                    FixedNode next = fixedNode.next();
                     fixedNode.setNext(a);
+                    a.setNext(next);
                     this.anchor = a;
                 }
             } 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,6 +30,8 @@
 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.NodeClass.*;
+import com.oracle.max.graal.graph.collections.*;
 
 
 public class IdentifyBlocksPhase extends Phase {
@@ -123,7 +125,7 @@
     }
 
     public static boolean isFixed(Node n) {
-        return n != null && ((n instanceof FixedNode) || n == n.graph().start());
+        return n != null && ((n instanceof FixedNode) || n == n.graph().start()) && !(n instanceof AccessNode && n.predecessor() == null);
     }
 
     public static boolean isBlockEnd(Node n) {
@@ -162,12 +164,13 @@
                     if (currentNode instanceof FixedNode) {
                         block.setProbability(((FixedNode) currentNode).probability());
                     }
-                    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 instanceof AccessNode && ((AccessNode) currentNode).next() != prev) : currentNode;
                     assert !currentNode.isDeleted() : prev + " " + currentNode;
                 }
             }
@@ -183,9 +186,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);
                     }
                 }
@@ -326,13 +329,13 @@
         // if in CFG, schedule at the latest position possible in the outermost loop possible
         // if floating, use rematerialization to place the node, it tries to compute the value only when it will be used,
         // in the block with the smallest probability (outside of loops), while minimizing live ranges
-        if (!splitMaterialization || noRematerialization(n) || n.predecessors().size() > 0 || nonNullSuccessorCount(n) > 0) {
+        if (!splitMaterialization || noRematerialization(n) || n.predecessor() != null || nonNullSuccessorCount(n) > 0) {
             Block latestBlock = latestBlock(n);
             //TTY.println("Latest for " + n + " : " + latestBlock);
             Block block;
             if (latestBlock == null) {
                 block = earliestBlock(n);
-            } else if (GraalOptions.ScheduleOutOfLoops) {
+            } else if (GraalOptions.ScheduleOutOfLoops && !(n instanceof VirtualObjectField) && !(n instanceof VirtualObject)) {
                 block = scheduleOutOfLoops(n, latestBlock, earliestBlock(n));
             } else {
                 block = latestBlock;
@@ -385,9 +388,10 @@
             if (nodeToBlock.get(node) == null) {
                 n = node;
             } else {
-                n = node.copy();
-                for (int i = 0; i < node.inputs().size(); i++) {
-                    n.inputs().set(i, node.inputs().get(i));
+                n = node.copy(node.graph());
+                for (NodeClassIterator iter = node.inputs().iterator(); iter.hasNext();) {
+                    Position pos = iter.nextPosition();
+                    n.getNodeClass().set(n, pos, node.getNodeClass().get(node, pos));
                 }
                 for (Usage usage : blockUsages) {
                     patch(usage, node, n);
@@ -462,9 +466,13 @@
             return earliest;
         }
         BitMap bits = new BitMap(blocks.size());
-        ArrayList<Node> before = new ArrayList<Node>(n.predecessors().size() + n.inputs().size());
-        before.addAll(n.predecessors());
-        before.addAll(n.inputs());
+        ArrayList<Node> before = new ArrayList<Node>();
+        if (n.predecessor() != null) {
+            before.add(n.predecessor());
+        }
+        for (Node input : n.inputs()) {
+            before.add(input);
+        }
         for (Node pred : before) {
             if (pred == null) {
                 continue;
@@ -517,7 +525,7 @@
                         TTY.println(phi.inputs().toString());
                         TTY.println("value count: " + phi.valueCount());
                     }
-                    closure.apply(mergeBlock.getPredecessors().get(i));
+                closure.apply(mergeBlock.getPredecessors().get(i));
                 }
             }
         } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) {
@@ -565,8 +573,7 @@
 
     private void ensureScheduledUsages(Node node) {
         //  assign block to all usages to ensure that any splitting/rematerialization is done on them
-        List<Node> usages = new ArrayList<Node>(node.usages());
-        for (Node usage : usages) {
+        for (Node usage : node.usages().snapshot()) {
             assignBlockToNode(usage);
         }
         // now true usages are ready
@@ -620,7 +627,8 @@
     }
 
     private boolean noRematerialization(Node n) {
-        return n instanceof Local || n instanceof LocationNode || n instanceof Constant || n instanceof StateSplit || n instanceof FrameState;
+        return n instanceof Local || n instanceof LocationNode || n instanceof Constant || n instanceof StateSplit || n instanceof FrameState || n instanceof VirtualObject ||
+                        n instanceof VirtualObjectField;
     }
 
     private double liveRange(Block from, Set<Usage> usages) {
@@ -730,8 +738,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/target/amd64/AMD64LIRAssembler.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Fri Aug 05 18:44:32 2011 +0200
@@ -1170,16 +1170,12 @@
 
         Label continuation = new Label();
 
-        if (GraalOptions.GenSpecialDivChecks) {
+        if (GraalOptions.GenSpecialDivChecks && code == LIROpcode.Div) {
             // check for special case of Long.MIN_VALUE / -1
             Label normalCase = new Label();
             masm.movq(AMD64.rdx, java.lang.Long.MIN_VALUE);
             masm.cmpq(AMD64.rax, AMD64.rdx);
             masm.jcc(ConditionFlag.notEqual, normalCase);
-            if (code == LIROpcode.Lrem) {
-                // prepare X86Register.rdx for possible special case (where remainder = 0)
-                masm.xorq(AMD64.rdx, AMD64.rdx);
-            }
             masm.cmpl(rreg, -1);
             masm.jcc(ConditionFlag.equal, continuation);
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java	Fri Aug 05 18:44:32 2011 +0200
@@ -31,7 +31,9 @@
 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.NodeClass.*;
+import com.oracle.max.graal.graph.collections.*;
+import com.oracle.max.graal.graph.collections.NodeWorkList.InfiniteWorkException;
 
 public class GraphUtil {
 
@@ -230,18 +232,18 @@
                                 Phi phi = new Phi(((Value) node).kind, lambda.merge(color), PhiType.Value, node.graph());
                                 for (T parentColor : parentColors) {
                                     Node input = newNodes.get(parentColor);
-                                    phi.addInput(input);
+                                    phi.addInput((Value) input);
                                 }
                                 newNode = phi;
                             } else {
-                                newNode = node.copy();
-                                for (int i = 0; i < node.inputs().size(); i++) {
-                                    Node input = node.inputs().get(i);
-                                    newNode.inputs().setOrExpand(i, input);
+                                newNode = node.copy(node.graph());
+                                for (NodeClassIterator iter = node.inputs().iterator(); iter.hasNext();) {
+                                    Position pos = iter.nextPosition();
+                                    newNode.set(pos, node.get(pos));
                                 }
-                                for (int i = 0; i < node.successors().size(); i++) {
-                                    Node input = node.successors().get(i);
-                                    newNode.successors().setOrExpand(i, input);
+                                for (NodeClassIterator iter = node.successors().iterator(); iter.hasNext();) {
+                                    Position pos = iter.nextPosition();
+                                    newNode.set(pos, node.get(pos));
                                 }
                                 internalColoring.put(newNode, color);
                                 lambda.fixSplit(node, newNode, color);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Fri Aug 05 18:44:32 2011 +0200
@@ -34,6 +34,8 @@
 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.NodeClass.*;
+import com.oracle.max.graal.graph.collections.*;
 import com.sun.cri.ci.*;
 
 public class LoopUtil {
@@ -237,7 +239,7 @@
         // move peeled part to the end
         LoopBegin loopBegin = loop.loopBegin();
         LoopEnd loopEnd = loopBegin.loopEnd();
-        FixedNode lastNode = (FixedNode) loopEnd.singlePredecessor();
+        FixedNode lastNode = (FixedNode) loopEnd.predecessor();
         if (loopBegin.next() != lastNode) {
             lastNode.successors().replace(loopEnd, loopBegin.next());
             loopBegin.setNext(noExit);
@@ -249,8 +251,7 @@
         for (Phi phi : loopBegin.phis()) {
             Value backValue = phi.valueAt(backIndex);
             if (loop.nodes().isMarked(backValue) && peeling.peeledNodes.isNotNewNotMarked(backValue)) {
-                List<Node> usages = new ArrayList<Node>(phi.usages());
-                for (Node usage : usages) {
+                for (Node usage : phi.usages().snapshot()) {
                     if (peeling.peeledNodes.isNotNewMarked(usage)) {
                         usage.inputs().replace(phi, backValue);
                     }
@@ -306,23 +307,23 @@
     private static void rewirePeeling(PeelingResult peeling, Loop loop, FixedNode from, boolean inversion) {
         LoopBegin loopBegin = loop.loopBegin();
         Graph graph = loopBegin.graph();
-        Node loopPred = loopBegin.singlePredecessor();
+        Node loopPred = loopBegin.predecessor();
         loopPred.successors().replace(loopBegin.forwardEdge(), peeling.begin);
         NodeBitMap loopNodes = loop.cfgNodes();
         Node originalLast = from;
         if (originalLast == loopBegin.loopEnd()) {
-            originalLast = loopBegin.loopEnd().singlePredecessor();
+            originalLast = loopBegin.loopEnd().predecessor();
         }
-        int size = originalLast.successors().size();
         boolean found = false;
-        for (int i = 0; i < size; i++) {
-            Node sux = originalLast.successors().get(i);
+        for (NodeClassIterator iter = originalLast.successors().iterator(); iter.hasNext();) {
+            Position pos = iter.nextPosition();
+            Node sux = originalLast.getNodeClass().get(originalLast, pos);
             if (sux == null) {
                 continue;
             }
             if (loopNodes.isMarked(sux)) {
                 assert !found;
-                peeling.end.successors().set(i, loopBegin.forwardEdge());
+                peeling.end.getNodeClass().set(peeling.end, pos, loopBegin.forwardEdge());
                 found = true;
             }
         }
@@ -379,7 +380,7 @@
             EndNode oEnd = (EndNode) original.next();
             Merge merge = oEnd.merge();
             EndNode nEnd = merge.endAt(1 - merge.phiPredecessorIndex(oEnd));
-            Node newExit = nEnd.singlePredecessor();
+            Node newExit = nEnd.predecessor();
             for (Entry<Node, Node> dataEntry : peeling.dataOut.entries()) {
                 Node originalValue = dataEntry.getKey();
                 Node newValue = dataEntry.getValue();
@@ -419,8 +420,7 @@
                 }
                 Value newValue = (Value) entry.getValue();
                 Phi phi = null;
-                List<Node> usages = new ArrayList<Node>(originalValue.usages());
-                for (Node usage : usages) {
+                for (Node usage : originalValue.usages().snapshot()) {
                     if (exitMergesPhis.isMarked(usage) || (
                                     loop.nodes().isNotNewMarked(usage)
                                     && peeling.peeledNodes.isNotNewNotMarked(usage)
@@ -550,7 +550,7 @@
             }
             @Override
             public boolean explore(Node n) {
-                return exitFrameStates.isNotNewMarked(n) || (inOrBefore.isNotNewNotMarked(n) && n.inputs().size() > 0 && !afterColoringFramestate(n)); //TODO (gd) hum
+                return exitFrameStates.isNotNewMarked(n) || (inOrBefore.isNotNewNotMarked(n) && n.getNodeClass().directInputCount() > 0 && !afterColoringFramestate(n)); //TODO (gd) hum
             }
             public boolean afterColoringFramestate(Node n) {
                 if (!(n instanceof FrameState)) {
@@ -581,15 +581,16 @@
                     }
                     inOrBefore.mark(node);
                 } else {
-                    for (int i = 0; i < node.inputs().size(); i++) {
-                        Node input = node.inputs().get(i);
+                    for (NodeClassIterator iter = node.inputs().iterator(); iter.hasNext();) {
+                        Position pos = iter.nextPosition();
+                        Node input = node.getNodeClass().get(node, pos);
                         if (input == null || newExitValues.isNew(input)) {
                             continue;
                         }
                         NodeMap<Value> valueMap = newExitValues.get(input);
                         if (valueMap != null) {
                             Value replacement = getValueAt(color, valueMap, ((Value) input).kind);
-                            node.inputs().set(i, replacement);
+                            node.getNodeClass().set(node, pos, replacement);
                         }
                     }
                 }
@@ -639,7 +640,7 @@
         NodeBitMap clonedExits = graph.createNodeBitMap();
         NodeBitMap exitFrameStates = graph.createNodeBitMap();
         for (Node exit : loop.exits()) {
-            if (marked.isMarked(exit.singlePredecessor())) {
+            if (marked.isMarked(exit.predecessor())) {
                 StateSplit pExit = findNearestMergableExitPoint((FixedNode) exit, marked);
                 markWithState(pExit, marked);
                 clonedExits.mark(pExit);
@@ -714,7 +715,7 @@
         }
 
         FixedNode newBegin = (FixedNode) duplicates.get(loopBegin.next());
-        FixedNode newFrom = (FixedNode) duplicates.get(from == loopBegin.loopEnd() ? from.singlePredecessor() : from);
+        FixedNode newFrom = (FixedNode) duplicates.get(from == loopBegin.loopEnd() ? from.predecessor() : from);
         return new PeelingResult(newBegin, newFrom, exits, phis, phiInits, dataOutMapping, unaffectedExits, exitFrameStates, marked);
     }
 
@@ -795,8 +796,8 @@
         for (Node n : work) {
             inOrBefore.mark(n);
             if (full) {
-                for (Node pred : n.predecessors()) {
-                    work.add(pred);
+                if (n.predecessor() != null) {
+                    work.add(n.predecessor());
                 }
             }
             if (n instanceof Phi) { // filter out data graph cycles
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Fri Aug 05 18:44:32 2011 +0200
@@ -427,7 +427,7 @@
     }
 
     @SuppressWarnings("unchecked")
-    public static <T extends Node> Collection<T> filter(Collection<Node> nodes, Class<T> clazz) {
+    public static <T extends Node> Collection<T> filter(Iterable<Node> nodes, Class<T> clazz) {
         ArrayList<T> phis = new ArrayList<T>();
         for (Node node : nodes) {
             if (clazz.isInstance(node)) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Fri Aug 05 18:44:32 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.isEmpty() ? null : 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	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizerImpl.java	Fri Aug 05 18:44:32 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.*;
 
@@ -69,7 +70,7 @@
         // look at all loop exits:
         for (Node exit : exits) {
             TTY.println("exit: " + exit);
-            Node pred = exit.predecessors().get(0);
+            Node pred = exit.predecessor();
             // if this exit is an If node ...
             if (pred instanceof If) {
                 If ifNode = (If) pred;
--- a/graal/com.oracle.max.graal.graphviz/src/com/oracle/max/graal/graphviz/GraphvizPrinter.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.graphviz/src/com/oracle/max/graal/graphviz/GraphvizPrinter.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,7 +30,8 @@
 
 import com.oracle.max.graal.graph.Graph;
 import com.oracle.max.graal.graph.Node;
-import com.oracle.max.graal.graph.NodeArray;
+import com.oracle.max.graal.graph.NodeInputsIterable;
+import com.oracle.max.graal.graph.NodeSuccessorsIterable;
 
 /**
  * Generates a representation of {@link Node Nodes} or entire {@link Graph Graphs} in the DOT language that can be
@@ -105,32 +106,34 @@
         }
         int id = node.id();
         String name = "n" + id;
-        NodeArray inputs = node.inputs();
-        NodeArray successors = node.successors();
+        NodeInputsIterable inputs = node.inputs();
+        NodeSuccessorsIterable successors = node.successors();
 
         String color = classColors.get(node.getClass());
 
         if (shortNames) {
-            printNode(name, node.id(), excapeLabel(node.shortName()), color, inputs.size(), successors.size());
+            printNode(name, node.id(), excapeLabel(node.shortName()), color, inputs.explicitCount(), successors.explicitCount());
         } else {
-            printNode(name, node.id(), excapeLabel(node.toString()), color, inputs.size(), successors.size());
+            printNode(name, node.id(), excapeLabel(node.toString()), color, inputs.explicitCount(), successors.explicitCount());
         }
 
-        for (int i = 0; i < successors.size(); ++i) {
-            Node successor = successors.get(i);
+        int i = 0;
+        for (Node successor : successors) {
             if (successor != Node.Null && !omittedClasses.contains(successor.getClass())) {
                 printControlEdge(id, i, successor.id());
             }
+            i++;
         }
 
-        for (int i = 0; i < inputs.size(); ++i) {
-            Node input = inputs.get(i);
+        i = 0;
+        for (Node input : inputs) {
             if (input != Node.Null && !omittedClasses.contains(input.getClass())) {
                 if (node.getClass().getSimpleName().equals("FrameState") && input.getClass().getSimpleName().equals("Local")) {
                     continue;
                 }
                 printDataEdge(id, i, input.id());
             }
+            i++;
         }
     }
 
--- a/graal/com.oracle.max.graal.graphviz/test/com/oracle/graal/graph/vis/GraphvizTest.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.graphviz/test/com/oracle/graal/graph/vis/GraphvizTest.java	Fri Aug 05 18:44:32 2011 +0200
@@ -33,6 +33,10 @@
 
 import com.oracle.max.graal.graph.Graph;
 import com.oracle.max.graal.graph.Node;
+import com.oracle.max.graal.graph.NodeInput;
+import com.oracle.max.graal.graph.NodeInputList;
+import com.oracle.max.graal.graph.NodeSuccessor;
+import com.oracle.max.graal.graph.NodeSuccessorList;
 import com.oracle.max.graal.graphviz.GraphvizPrinter;
 import com.oracle.max.graal.graphviz.GraphvizRunner;
 
@@ -78,39 +82,33 @@
 
     private static class DummyNode extends Node {
 
-        private final int inputCount;
-        private final int successorCount;
-        private final String name;
+        @NodeInput
+        private final NodeInputList<Node> inputs;
+
+        @NodeSuccessor
+        private final NodeSuccessorList<Node> successors;
 
         public DummyNode(String name, int inputCount, int successorCount, Graph graph) {
-            super(inputCount, successorCount, graph);
+            super(graph);
             this.name = name;
-            this.inputCount = inputCount;
-            this.successorCount = successorCount;
+            inputs = new NodeInputList<Node>(this, inputCount);
+            successors = new NodeSuccessorList<Node>(this, successorCount);
+        }
+
+        public void setInput(int idx, Node n) {
+            inputs.set(idx, n);
+        }
+
+        public void setSuccessor(int idx, Node n) {
+            successors.set(idx, n);
         }
 
         @Override
         public Node copy(Graph into) {
-            return new DummyNode(name, inputCount, successorCount, into);
-        }
-
-        public void setInput(int idx, Node n) {
-            inputs().set(idx, n);
+            return new DummyNode(name, inputs.size(), successors.size(), into);
         }
 
-        public void setSuccessor(int idx, Node n) {
-            successors().set(idx, n);
-        }
-
-        @Override
-        protected int inputCount() {
-            return super.inputCount() + inputCount;
-        }
-
-        @Override
-        protected int successorCount() {
-            return super.inputCount() + successorCount;
-        }
+        private final String name;
 
         @Override
         public String toString() {
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotField.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotField.java	Fri Aug 05 18:44:32 2011 +0200
@@ -26,8 +26,7 @@
 import java.lang.reflect.*;
 
 import com.oracle.max.graal.compiler.*;
-import com.sun.cri.ci.CiConstant;
-import com.sun.cri.ci.CiKind;
+import com.sun.cri.ci.*;
 import com.sun.cri.ri.RiField;
 import com.sun.cri.ri.RiType;
 
@@ -130,7 +129,7 @@
 
     @Override
     public String toString() {
-        return "HotSpotField<" + holder.name() + "." + name + ":" + offset + ">";
+        return "HotSpotField<" + CiUtil.format("%h.%n", this, false) + ":" + offset + ">";
     }
 
 }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Fri Aug 05 18:44:32 2011 +0200
@@ -166,7 +166,7 @@
 
     @Override
     public String toString() {
-        return "HotSpotMethod<" + holder().name() + ". " + name + ">";
+        return "HotSpotMethod<" + CiUtil.format("%h.%n", this, false) + ">";
     }
 
     public boolean hasCompiledCode() {
@@ -218,15 +218,15 @@
         TTY.println("canBeStaticallyBound: " + canBeStaticallyBound());
         TTY.println("invocationCount: " + invocationCount());
         for (int i = 0; i < codeSize(); i++) {
-            if (exceptionProbability(i) > 0) {
-                TTY.println("  exceptionProbability@%d: %d", i, exceptionProbability(i));
-            }
             if (branchProbability(i) != -1) {
                 TTY.println("  branchProbability@%d: %f", i, branchProbability(i));
             }
             RiTypeProfile profile = typeProfile(i);
             if (profile != null && profile.count > 0) {
                 TTY.println("  profile@%d: count: %d, morphism: %d", i, profile.count, profile.morphism);
+                if (exceptionProbability(i) != -1) {
+                    TTY.println("  exceptionProbability@%d: %d", i, exceptionProbability(i));
+                }
             }
         }
     }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Fri Aug 05 18:44:32 2011 +0200
@@ -263,7 +263,9 @@
             assert field.kind != CiKind.Illegal;
             ReadNode memoryRead = new ReadNode(field.field().kind().stackKind(), field.object(), LocationNode.create(field.field(), field.field().kind(), displacement, graph), graph);
             memoryRead.setGuard((GuardNode) tool.createGuard(new IsNonNull(field.object(), graph)));
-            memoryRead.setNext(field.next());
+            FixedNode next = field.next();
+            field.setNext(null);
+            memoryRead.setNext(next);
             field.replaceAndDelete(memoryRead);
         } else if (n instanceof StoreField) {
             StoreField field = (StoreField) n;
@@ -275,13 +277,14 @@
             WriteNode memoryWrite = new WriteNode(CiKind.Illegal, field.object(), field.value(), LocationNode.create(field.field(), field.field().kind(), displacement, graph), graph);
             memoryWrite.setGuard((GuardNode) tool.createGuard(new IsNonNull(field.object(), graph)));
             memoryWrite.setStateAfter(field.stateAfter());
-            memoryWrite.setNext(field.next());
+            FixedNode next = field.next();
+            field.setNext(null);
             if (field.field().kind() == CiKind.Object && !field.value().isNullConstant()) {
                 FieldWriteBarrier writeBarrier = new FieldWriteBarrier(field.object(), graph);
                 memoryWrite.setNext(writeBarrier);
-                writeBarrier.setNext(field.next());
+                writeBarrier.setNext(next);
             } else {
-                memoryWrite.setNext(field.next());
+                memoryWrite.setNext(next);
             }
             field.replaceAndDelete(memoryWrite);
         } else if (n instanceof LoadIndexed) {
@@ -294,7 +297,9 @@
             arrayLocation.setIndex(loadIndexed.index());
             ReadNode memoryRead = new ReadNode(elementKind.stackKind(), loadIndexed.array(), arrayLocation, graph);
             memoryRead.setGuard(boundsCheck);
-            memoryRead.setNext(loadIndexed.next());
+            FixedNode next = loadIndexed.next();
+            loadIndexed.setNext(null);
+            memoryRead.setNext(next);
             loadIndexed.replaceAndDelete(memoryRead);
         } else if (n instanceof StoreIndexed) {
             StoreIndexed storeIndexed = (StoreIndexed) n;
@@ -327,16 +332,47 @@
             WriteNode memoryWrite = new WriteNode(elementKind.stackKind(), array, value, arrayLocation, graph);
             memoryWrite.setGuard(boundsCheck);
             memoryWrite.setStateAfter(storeIndexed.stateAfter());
+            FixedNode next = storeIndexed.next();
+            storeIndexed.setNext(null);
             anchor.setNext(memoryWrite);
             if (elementKind == CiKind.Object && !value.isNullConstant()) {
                 ArrayWriteBarrier writeBarrier = new ArrayWriteBarrier(array, arrayLocation, graph);
                 memoryWrite.setNext(writeBarrier);
-                writeBarrier.setNext(storeIndexed.next());
+                writeBarrier.setNext(next);
             } else {
-                memoryWrite.setNext(storeIndexed.next());
+                memoryWrite.setNext(next);
             }
             storeIndexed.replaceAtPredecessors(anchor);
             storeIndexed.delete();
+        } else if (n instanceof UnsafeLoad) {
+            UnsafeLoad load = (UnsafeLoad) n;
+            Graph graph = load.graph();
+            assert load.kind != CiKind.Illegal;
+            LocationNode location = LocationNode.create(LocationNode.UNSAFE_ACCESS_LOCATION, load.kind, 0, graph);
+            location.setIndex(load.offset());
+            location.setIndexScalingEnabled(false);
+            ReadNode memoryRead = new ReadNode(load.kind.stackKind(), load.object(), location, graph);
+            memoryRead.setGuard((GuardNode) tool.createGuard(new IsNonNull(load.object(), graph)));
+            FixedNode next = load.next();
+            load.setNext(null);
+            memoryRead.setNext(next);
+            load.replaceAndDelete(memoryRead);
+        } else if (n instanceof UnsafeStore) {
+            UnsafeStore store = (UnsafeStore) n;
+            Graph graph = store.graph();
+            assert store.kind != CiKind.Illegal;
+            LocationNode location = LocationNode.create(LocationNode.UNSAFE_ACCESS_LOCATION, store.kind, 0, graph);
+            location.setIndex(store.offset());
+            location.setIndexScalingEnabled(false);
+            WriteNode write = new WriteNode(store.kind.stackKind(), store.object(), store.value(), location, graph);
+            FieldWriteBarrier barrier = new FieldWriteBarrier(store.object(), graph);
+            FixedNode next = store.next();
+            store.setNext(null);
+            barrier.setNext(next);
+            write.setNext(barrier);
+            write.setStateAfter(store.stateAfter());
+            store.replaceAtPredecessors(write);
+            store.delete();
         }
     }
 
@@ -514,6 +550,31 @@
                     graph.setReturn(ret);
                     intrinsicGraphs.put(method, graph);
                 }
+            } else if (holderName.equals("Lsun/misc/Unsafe;")) {
+                if (fullName.equals("getObject(Ljava/lang/Object;J)Ljava/lang/Object;")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Local object = new Local(CiKind.Object, 1, graph);
+                    Local offset = new Local(CiKind.Long, 2, graph);
+                    UnsafeLoad load = new UnsafeLoad(object, offset, CiKind.Object, graph);
+                    Return ret = new Return(load, graph);
+                    load.setNext(ret);
+                    graph.start().setNext(load);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                } else if (fullName.equals("putObject(Ljava/lang/Object;JLjava/lang/Object;)V")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Local object = new Local(CiKind.Object, 1, graph);
+                    Local offset = new Local(CiKind.Long, 2, graph);
+                    Local value = new Local(CiKind.Object, 3, graph);
+                    UnsafeStore store = new UnsafeStore(object, offset, value, CiKind.Object, graph);
+                    FrameState frameState = new FrameState(method, FrameState.AFTER_BCI, 0, 0, 0, false, graph);
+                    store.setStateAfter(frameState);
+                    Return ret = new Return(null, graph);
+                    store.setNext(ret);
+                    graph.start().setNext(store);
+                    graph.setReturn(ret);
+                    intrinsicGraphs.put(method, graph);
+                }
             }
 
             if (!intrinsicGraphs.containsKey(method)) {
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotTypeUnresolved.java	Fri Aug 05 18:44:32 2011 +0200
@@ -68,11 +68,11 @@
     }
 
     private String getFullName(String name, int dimensions) {
-        StringBuilder str = new StringBuilder();
+        StringBuilder str = new StringBuilder(name.length() + dimensions + 2);
         for (int i = 0; i < dimensions; i++) {
             str.append('[');
         }
-        str.append('L').append(simpleName).append(';');
+        str.append('L').append(name).append(';');
         return str.toString();
     }
 
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMExitsNative.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/VMExitsNative.java	Fri Aug 05 18:44:32 2011 +0200
@@ -30,6 +30,7 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.runtime.logging.*;
 import com.oracle.max.graal.runtime.server.*;
 import com.sun.cri.ci.*;
@@ -85,7 +86,6 @@
             @Override
             public void run() {
                 if (GraalOptions.Meter) {
-
                     GraalMetrics.print();
                 }
                 if (GraalOptions.Time) {
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/ArrayWriteBarrier.java	Fri Aug 05 18:44:32 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/CurrentThread.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/CurrentThread.java	Fri Aug 05 18:44:32 2011 +0200
@@ -31,12 +31,11 @@
 
 
 public final class CurrentThread extends FloatingNode {
-    private static final int INPUT_COUNT = 0;
-    private static final int SUCCESSOR_COUNT = 0;
+
     private int threadObjectOffset;
 
     public CurrentThread(int threadObjectOffset, Graph graph) {
-        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Object, graph);
         this.threadObjectOffset = threadObjectOffset;
     }
 
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java	Fri Aug 05 18:44:32 2011 +0200
@@ -32,26 +32,21 @@
 
 
 public final class FPConversionNode extends FloatingNode {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_OBJECT = 0;
 
-    private static final int SUCCESSOR_COUNT = 0;
+    @NodeInput
+    private Value value;
 
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
+    public Value value() {
+        return value;
     }
 
-     public Value value() {
-        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
-    }
-
-    public void setValue(Value n) {
-        inputs().set(super.inputCount() + INPUT_OBJECT, n);
+    public void setValue(Value x) {
+        updateUsages(value, x);
+        value = x;
     }
 
     public FPConversionNode(CiKind kind, Value value, Graph graph) {
-        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, graph);
         this.setValue(value);
     }
 
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FieldWriteBarrier.java	Fri Aug 05 18:44:32 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);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/UnsafeLoad.java	Fri Aug 05 18:44:32 2011 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.runtime.nodes;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Load of a value from a location specified as an offset relative to an object.
+ */
+public class UnsafeLoad extends StateSplit {
+
+    @NodeInput
+    private Value object;
+
+    @NodeInput
+    private Value offset;
+
+    public Value object() {
+        return object;
+    }
+
+    public void setObject(Value x) {
+        updateUsages(object, x);
+        object = x;
+    }
+
+    public Value offset() {
+        return offset;
+    }
+
+    public void setOffset(Value x) {
+        updateUsages(offset, x);
+        offset = x;
+    }
+
+    public UnsafeLoad(Value object, Value offset, CiKind kind, Graph graph) {
+        super(kind, graph);
+        setObject(object);
+        setOffset(offset);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        UnsafeLoad x = new UnsafeLoad(null, null, kind, into);
+        super.copyInto(x);
+        return x;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/UnsafeStore.java	Fri Aug 05 18:44:32 2011 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.runtime.nodes;
+
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * Store of a value at a location specified as an offset relative to an object.
+ */
+public class UnsafeStore extends StateSplit {
+
+    @NodeInput
+    private Value object;
+
+    @NodeInput
+    private Value offset;
+
+    @NodeInput
+    private Value value;
+
+    public Value object() {
+        return object;
+    }
+
+    public void setObject(Value x) {
+        updateUsages(object, x);
+        object = x;
+    }
+
+    public Value offset() {
+        return offset;
+    }
+
+    public void setOffset(Value x) {
+        updateUsages(offset, x);
+        offset = x;
+    }
+
+    public Value value() {
+        return value;
+    }
+
+    public void setValue(Value x) {
+        updateUsages(value, x);
+        value = x;
+    }
+
+    public UnsafeStore(Value object, Value offset, Value value, CiKind kind, Graph graph) {
+        super(kind, graph);
+        setObject(object);
+        setOffset(offset);
+        setValue(value);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        UnsafeStore x = new UnsafeStore(null, null, null, kind, into);
+        super.copyInto(x);
+        return x;
+    }
+
+}
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java	Fri Aug 05 17:42:04 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/WriteBarrier.java	Fri Aug 05 18:44:32 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);
     }
 
 
--- a/runfop.sh	Fri Aug 05 17:42:04 2011 +0200
+++ b/runfop.sh	Fri Aug 05 18:44:32 2011 +0200
@@ -15,4 +15,4 @@
   echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
   exit 1;
 fi
-${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar -XX:-GraalBailoutIsFatal $* Harness --preserve -n 20 fop 
+${JDK7}/bin/java -client -d64 -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar -XX:-GraalBailoutIsFatal $* Harness --preserve -n 100 fop 
--- a/src/cpu/x86/vm/c1_globals_x86.hpp	Fri Aug 05 17:42:04 2011 +0200
+++ b/src/cpu/x86/vm/c1_globals_x86.hpp	Fri Aug 05 18:44:32 2011 +0200
@@ -40,7 +40,7 @@
 define_pd_global(bool, ProfileTraps,                 true );
 define_pd_global(bool, UseOnStackReplacement,        true );
 define_pd_global(bool, TieredCompilation,            false);
-define_pd_global(intx, CompileThreshold,             5000 );   // changed for GRAAL
+define_pd_global(intx, CompileThreshold,             4500 );   // changed for GRAAL
 define_pd_global(intx, BackEdgeThreshold,            100000);
 
 define_pd_global(intx, OnStackReplacePercentage,     933  );
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Aug 05 17:42:04 2011 +0200
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Aug 05 18:44:32 2011 +0200
@@ -413,6 +413,7 @@
   template(bitCount_name,                             "bitCount")                                 \
   template(profile_name,                              "profile")                                  \
   template(equals_name,                               "equals")                                   \
+  template(length_name,                               "length")                                   \
   template(target_name,                               "target")                                   \
   template(toString_name,                             "toString")                                 \
   template(values_name,                               "values")                                   \
--- a/src/share/vm/compiler/compileBroker.cpp	Fri Aug 05 17:42:04 2011 +0200
+++ b/src/share/vm/compiler/compileBroker.cpp	Fri Aug 05 18:44:32 2011 +0200
@@ -642,6 +642,17 @@
   }
 }
 
+void CompileBroker::add_method_to_queue(klassOop k, Symbol* name, Symbol* signature) {
+  Thread* THREAD = Thread::current();
+  instanceKlass* klass = instanceKlass::cast(k);
+  methodOop method = klass->find_method(name, signature);
+  CompileBroker::compile_method(method, -1, 0, method, 0, "initial compile of object initializer", THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    CLEAR_PENDING_EXCEPTION;
+    fatal("error inserting method into compile queue");
+  }
+}
+
 // Bootstrap the graal compiler. Compiles all methods until compile queue is empty and no compilation is active.
 void CompileBroker::bootstrap_graal() {
   HandleMark hm;
@@ -652,14 +663,10 @@
   if (compiler == NULL) fatal("must use flag -XX:+UseGraal");
 
   jlong start = os::javaTimeMillis();
-
-  instanceKlass* klass = (instanceKlass*)SystemDictionary::Object_klass()->klass_part();
-  methodOop method = klass->find_method(vmSymbols::object_initializer_name(), vmSymbols::void_method_signature());
-  CompileBroker::compile_method(method, -1, 0, method, 0, "initial compile of object initializer", THREAD);
-  if (HAS_PENDING_EXCEPTION) {
-    CLEAR_PENDING_EXCEPTION;
-    fatal("error inserting object initializer into compile queue");
-  }
+  add_method_to_queue(SystemDictionary::Object_klass(), vmSymbols::object_initializer_name(), vmSymbols::void_method_signature());
+  add_method_to_queue(SystemDictionary::Object_klass(), vmSymbols::equals_name(), vmSymbols::object_boolean_signature());
+  add_method_to_queue(SystemDictionary::String_klass(), vmSymbols::length_name(), vmSymbols::void_int_signature());
+  add_method_to_queue(SystemDictionary::String_klass(), vmSymbols::object_initializer_name(), vmSymbols::void_method_signature());
 
   int z = 0;
   while (true) {
--- a/src/share/vm/compiler/compileBroker.hpp	Fri Aug 05 17:42:04 2011 +0200
+++ b/src/share/vm/compiler/compileBroker.hpp	Fri Aug 05 18:44:32 2011 +0200
@@ -403,6 +403,7 @@
   static void print_compiler_threads_on(outputStream* st);
 
   static void bootstrap_graal();
+  static void add_method_to_queue(klassOop k, Symbol* name, Symbol* signature);
 };
 
 #endif // SHARE_VM_COMPILER_COMPILEBROKER_HPP
--- a/src/share/vm/graal/graalVMEntries.cpp	Fri Aug 05 17:42:04 2011 +0200
+++ b/src/share/vm/graal/graalVMEntries.cpp	Fri Aug 05 18:44:32 2011 +0200
@@ -192,21 +192,19 @@
     methodOop method = getMethodFromHotSpotMethod(hotspot_method);
     cimethod = (ciMethod*)CURRENT_ENV->get_object(method);
   }
+  ciMethodData* method_data = cimethod->method_data();
 
-  ciMethodData* method_data = cimethod->method_data_or_null();
-  if (method_data == NULL) {
-    return -1;
+  if (method_data == NULL || !method_data->is_mature()) return -1;
+
+  ciProfileData* profile = method_data->bci_to_data(bci);
+  if (profile == NULL) {
+    return 0;
+  }
+  uint trap = method_data->trap_recompiled_at(profile);
+  if (trap > 0) {
+    return 100;
   } else {
-    ciProfileData* profile = method_data->bci_to_data(bci);
-    if (profile == NULL) {
-      return 0;
-    }
-    uint trap = method_data->trap_recompiled_at(profile);
-    if (trap > 0) {
-      return 100;
-    } else {
-      return trap;
-    }
+    return trap;
   }
 }