changeset 2606:f21f430a6ef2

Merge.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Fri, 06 May 2011 16:21:10 +0200
parents 98fa88528319 (current diff) 01c5c0443158 (diff)
children 008adfd6d850 32461558c98f
files
diffstat 38 files changed, 658 insertions(+), 412 deletions(-) [+]
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java	Fri May 06 16:21:10 2011 +0200
@@ -166,7 +166,7 @@
      */
     public BlockMap getBlockMap(RiMethod method) {
         // PERF: cache the block map for methods that are compiled or inlined often
-        BlockMap map = new BlockMap(method, hir.numberOfBlocks());
+        BlockMap map = new BlockMap(method, hir.numberOfBlocks(), hir.graph());
         if (!map.build(C1XOptions.PhiLoopStores)) {
             throw new CiBailout("build of BlockMap failed for " + method);
         } else {
@@ -309,4 +309,5 @@
     public static C1XCompilation compilationOrNull() {
         return currentCompilation.get();
     }
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java	Fri May 06 16:21:10 2011 +0200
@@ -22,8 +22,12 @@
  */
 package com.sun.c1x;
 
+import java.io.*;
 import java.util.*;
 
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.vis.*;
+import com.oracle.graal.graph.vis.GraphvizTest.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.globalstub.*;
 import com.sun.c1x.observer.*;
@@ -125,6 +129,47 @@
         if (C1XOptions.PrintCFGToFile) {
             addCompilationObserver(new CFGPrinterObserver());
         }
+        String dot = System.getProperty("c1x.dot");
+        if (dot != null && !dot.isEmpty()) {
+            if (!dot.endsWith("$")) {
+                dot = dot + ".*";
+            }
+            if (!dot.startsWith("^")) {
+                dot = ".*" + dot;
+            }
+            final String dotPattern = dot;
+            addCompilationObserver(new CompilationObserver() {
+                private Graph graph;
+                private int n;
+                public void compilationStarted(CompilationEvent event) {
+                    n = 0;
+                }
+                public void compilationFinished(CompilationEvent event) {
+                }
+                public void compilationEvent(CompilationEvent event) {
+                    if (event.getStartBlock() != null) {
+                        graph = event.getStartBlock().graph();
+                        String name = event.getMethod().holder().name();
+                        name = name.substring(1, name.length() - 1).replace('/', '.');
+                        name = name + "." + event.getMethod().name();
+                        if (name.matches(dotPattern)) {
+                            ByteArrayOutputStream out = new ByteArrayOutputStream();
+                            GraphvizPrinter printer = new GraphvizPrinter(out);
+                            printer.begin(name);
+                            printer.print(graph);
+                            printer.end();
+
+                            try {
+                                GraphvizRunner.process(GraphvizRunner.DOT_COMMAND, new ByteArrayInputStream(out.toByteArray()),
+                                                new FileOutputStream(name + "_" + (n++) + event.getLabel() + ".pdf"), "pdf");
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }
+                    }
+                }
+            });
+        }
     }
 
     public GlobalStub lookupGlobalStub(GlobalStub.Id id) {
--- a/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java	Fri May 06 16:21:10 2011 +0200
@@ -288,14 +288,14 @@
     @Override
     public void visitCheckCast(CheckCast x) {
         XirArgument obj = toXirArgument(x.object());
-        XirSnippet snippet = xir.genCheckCast(site(x), obj, toXirArgument(x.targetClassInstruction), x.targetClass());
+        XirSnippet snippet = xir.genCheckCast(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass());
         emitXir(snippet, x, stateFor(x), null, true);
     }
 
     @Override
     public void visitInstanceOf(InstanceOf x) {
         XirArgument obj = toXirArgument(x.object());
-        XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction), x.targetClass());
+        XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass());
         emitXir(snippet, x, maybeStateFor(x), null, true);
     }
 
@@ -347,10 +347,10 @@
 
     @Override
     public void visitNewMultiArray(NewMultiArray x) {
-        XirArgument[] dims = new XirArgument[x.dimensions().length];
+        XirArgument[] dims = new XirArgument[x.dimensionCount()];
 
         for (int i = 0; i < dims.length; i++) {
-            dims[i] = toXirArgument(x.dimensions()[i]);
+            dims[i] = toXirArgument(x.dimension(i));
         }
 
         XirSnippet snippet = xir.genNewMultiArray(site(x), dims, x.elementKind);
@@ -560,7 +560,7 @@
             int len = x.numberOfCases();
             for (int i = 0; i < len; i++) {
                 lir.cmp(Condition.EQ, tag, x.keyAt(i));
-                lir.branch(Condition.EQ, CiKind.Int, x.suxAt(i));
+                lir.branch(Condition.EQ, CiKind.Int, x.blockSuccessor(i));
             }
             lir.jump(x.defaultSuccessor());
         } else {
@@ -825,7 +825,7 @@
             int len = x.numberOfCases();
             for (int i = 0; i < len; i++) {
                 lir.cmp(Condition.EQ, tag, i + loKey);
-                lir.branch(Condition.EQ, CiKind.Int, x.suxAt(i));
+                lir.branch(Condition.EQ, CiKind.Int, x.blockSuccessor(i));
             }
             lir.jump(x.defaultSuccessor());
         } else {
@@ -1150,11 +1150,11 @@
         if (len > 0) {
             BlockBegin defaultSux = x.defaultSuccessor();
             int key = x.keyAt(0);
-            BlockBegin sux = x.suxAt(0);
+            BlockBegin sux = x.blockSuccessor(0);
             SwitchRange range = new SwitchRange(key, sux);
             for (int i = 1; i < len; i++) {
                 int newKey = x.keyAt(i);
-                BlockBegin newSux = x.suxAt(i);
+                BlockBegin newSux = x.blockSuccessor(i);
                 if (key + 1 == newKey && sux == newSux) {
                     // still in same range
                     range.highKey = newKey;
@@ -1180,12 +1180,12 @@
         List<SwitchRange> res = new ArrayList<SwitchRange>(x.numberOfCases());
         int len = x.numberOfCases();
         if (len > 0) {
-            BlockBegin sux = x.suxAt(0);
+            BlockBegin sux = x.blockSuccessor(0);
             int key = x.lowKey();
             BlockBegin defaultSux = x.defaultSuccessor();
             SwitchRange range = new SwitchRange(key, sux);
             for (int i = 0; i < len; i++, key++) {
-                BlockBegin newSux = x.suxAt(i);
+                BlockBegin newSux = x.blockSuccessor(i);
                 if (sux == newSux) {
                     // still in same range
                     range.highKey = key;
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/BlockMap.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/BlockMap.java	Fri May 06 16:21:10 2011 +0200
@@ -26,6 +26,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.ir.*;
 import com.sun.c1x.util.*;
 import com.sun.cri.bytecode.*;
@@ -115,8 +116,6 @@
  *
  * If the {@code computeStoresInLoops} argument to {@code build} is true, the {@code loopBlocks} list is processed to
  * mark all local variables that are stored in the blocks in the list.
- *
- * @author Ben L. Titzer
  */
 public final class BlockMap {
 
@@ -222,12 +221,16 @@
      */
     private int blockNum;
 
+    private final Graph graph;
+
     /**
      * Creates a new BlockMap instance from bytecode of the given method .
      * @param method the compiler interface method containing the code
      * @param firstBlockNum the first block number to use when creating {@link BlockBegin} nodes
+     * @param graph
      */
-    public BlockMap(RiMethod method, int firstBlockNum) {
+    public BlockMap(RiMethod method, int firstBlockNum, Graph graph) {
+        this.graph = graph;
         byte[] code = method.code();
         this.code = code;
         firstBlock = firstBlockNum;
@@ -265,7 +268,7 @@
     BlockBegin make(int bci) {
         BlockBegin block = blockMap[bci];
         if (block == null) {
-            block = new BlockBegin(bci, blockNum++);
+            block = new BlockBegin(bci, blockNum++, graph);
             blockMap[bci] = block;
         }
         return block;
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Fri May 06 16:21:10 2011 +0200
@@ -124,18 +124,16 @@
     boolean skipBlock;                     // skip processing of the rest of this block
     private Value rootMethodSynchronizedObject;
 
-
-
-    private Graph graph = new Graph();
-
+    private final Graph graph;
 
     /**
      * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation.
      *
      * @param compilation the compilation
      * @param ir the IR to build the graph into
+     * @param graph
      */
-    public GraphBuilder(C1XCompilation compilation, IR ir) {
+    public GraphBuilder(C1XCompilation compilation, IR ir, Graph graph) {
         this.compilation = compilation;
         this.ir = ir;
         this.stats = compilation.stats;
@@ -144,6 +142,7 @@
         log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null;
         stream = new BytecodeStream(compilation.method.code());
         constantPool = compilation.runtime.getConstantPool(compilation.method);
+        this.graph = graph;
     }
 
     /**
@@ -163,7 +162,7 @@
         }
 
         // 1. create the start block
-        ir.startBlock = new BlockBegin(0, ir.nextBlockNumber());
+        ir.startBlock = new BlockBegin(0, ir.nextBlockNumber(), graph);
         BlockBegin startBlock = ir.startBlock;
 
         // 2. compute the block map, setup exception handlers and get the entrypoint(s)
@@ -200,7 +199,7 @@
             finishStartBlock(startBlock, stdEntry);
 
             // 4A.3 setup an exception handler to unlock the root method synchronized object
-            syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, ir.nextBlockNumber());
+            syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, ir.nextBlockNumber(), graph);
             syncHandler.setExceptionEntry();
             syncHandler.setBlockFlag(BlockBegin.BlockFlag.IsOnWorkList);
             syncHandler.setBlockFlag(BlockBegin.BlockFlag.DefaultExceptionHandler);
@@ -227,7 +226,7 @@
 
     private void finishStartBlock(BlockBegin startBlock, BlockBegin stdEntry) {
         assert curBlock == startBlock;
-        Base base = new Base(stdEntry);
+        Base base = new Base(stdEntry, graph);
         appendWithoutOptimization(base, 0);
         FrameState stateAfter = curState.immutableCopy(bci());
         base.setStateAfter(stateAfter);
@@ -423,7 +422,7 @@
             // this is a load of class constant which might be unresolved
             RiType riType = (RiType) con;
             if (!riType.isResolved() || C1XOptions.TestPatching) {
-                push(CiKind.Object, append(new ResolveClass(riType, RiType.Representation.JavaClass, null)));
+                push(CiKind.Object, append(new ResolveClass(riType, RiType.Representation.JavaClass, null, graph)));
             } else {
                 push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph)));
             }
@@ -600,7 +599,7 @@
 
     void genGoto(int fromBCI, int toBCI) {
         boolean isSafepoint = !noSafepoints() && toBCI <= fromBCI;
-        append(new Goto(blockAt(toBCI), null, isSafepoint));
+        append(new Goto(blockAt(toBCI), null, isSafepoint, graph));
     }
 
     void ifNode(Value x, Condition cond, Value y, FrameState stateBefore) {
@@ -608,7 +607,7 @@
         BlockBegin fsucc = blockAt(stream().nextBCI());
         int bci = stream().currentBCI();
         boolean isSafepoint = !noSafepoints() && tsucc.bci() <= bci || fsucc.bci() <= bci;
-        append(new If(x, cond, y, tsucc, fsucc, isSafepoint ? stateBefore : null, isSafepoint));
+        append(new If(x, cond, y, tsucc, fsucc, isSafepoint ? stateBefore : null, isSafepoint, graph));
     }
 
     void genIfZero(Condition cond) {
@@ -634,7 +633,7 @@
 
     void genThrow(int bci) {
         FrameState stateBefore = curState.immutableCopy(bci());
-        Throw t = new Throw(apop(), stateBefore, !noSafepoints());
+        Throw t = new Throw(apop(), stateBefore, !noSafepoints(), graph);
         appendWithoutOptimization(t, bci);
     }
 
@@ -643,7 +642,7 @@
         RiType type = constantPool().lookupType(cpi, CHECKCAST);
         boolean isInitialized = !C1XOptions.TestPatching && type.isResolved() && type.isInitialized();
         Value typeInstruction = genResolveClass(RiType.Representation.ObjectHub, type, isInitialized, cpi);
-        CheckCast c = new CheckCast(type, typeInstruction, apop(), null);
+        CheckCast c = new CheckCast(type, typeInstruction, apop(), null, graph);
         apush(append(c));
         checkForDirectCompare(c);
     }
@@ -653,7 +652,7 @@
         RiType type = constantPool().lookupType(cpi, INSTANCEOF);
         boolean isInitialized = !C1XOptions.TestPatching && type.isResolved() && type.isInitialized();
         Value typeInstruction = genResolveClass(RiType.Representation.ObjectHub, type, isInitialized, cpi);
-        InstanceOf i = new InstanceOf(type, typeInstruction, apop(), null);
+        InstanceOf i = new InstanceOf(type, typeInstruction, apop(), null, graph);
         ipush(append(i));
         checkForDirectCompare(i);
     }
@@ -668,7 +667,7 @@
     void genNewInstance(int cpi) {
         FrameState stateBefore = curState.immutableCopy(bci());
         RiType type = constantPool().lookupType(cpi, NEW);
-        NewInstance n = new NewInstance(type, cpi, constantPool(), stateBefore);
+        NewInstance n = new NewInstance(type, cpi, constantPool(), stateBefore, graph);
         if (memoryMap != null) {
             memoryMap.newInstance(n);
         }
@@ -679,13 +678,13 @@
         FrameState stateBefore = curState.immutableCopy(bci());
         CiKind kind = CiKind.fromArrayTypeCode(typeCode);
         RiType elementType = compilation.runtime.asRiType(kind);
-        apush(append(new NewTypeArray(ipop(), elementType, stateBefore)));
+        apush(append(new NewTypeArray(ipop(), elementType, stateBefore, graph)));
     }
 
     void genNewObjectArray(int cpi) {
         RiType type = constantPool().lookupType(cpi, ANEWARRAY);
         FrameState stateBefore = curState.immutableCopy(bci());
-        NewArray n = new NewObjectArray(type, ipop(), stateBefore);
+        NewArray n = new NewObjectArray(type, ipop(), stateBefore, graph);
         apush(append(n));
     }
 
@@ -697,7 +696,7 @@
         for (int i = rank - 1; i >= 0; i--) {
             dims[i] = ipop();
         }
-        NewArray n = new NewMultiArray(type, dims, stateBefore, cpi, constantPool());
+        NewArray n = new NewMultiArray(type, dims, stateBefore, cpi, constantPool(), graph);
         apush(append(n));
     }
 
@@ -744,7 +743,7 @@
         if (initialized) {
             holderInstr = appendConstant(holder.getEncoding(representation));
         } else {
-            holderInstr = append(new ResolveClass(holder, representation, null));
+            holderInstr = append(new ResolveClass(holder, representation, null, graph));
         }
         return holderInstr;
     }
@@ -1001,7 +1000,7 @@
 
         if (needsCheck) {
             // append a call to the finalizer registration
-            append(new RegisterFinalizer(curState.loadLocal(0), curState.immutableCopy(bci())));
+            append(new RegisterFinalizer(curState.loadLocal(0), curState.immutableCopy(bci()), graph));
             C1XMetrics.InlinedFinalizerChecks++;
         }
     }
@@ -1018,13 +1017,13 @@
             int lockNumber = curState.locksSize() - 1;
             MonitorAddress lockAddress = null;
             if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
-                lockAddress = new MonitorAddress(lockNumber);
+                lockAddress = new MonitorAddress(lockNumber, graph);
                 append(lockAddress);
             }
             append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, stateBefore, graph));
             curState.unlock();
         }
-        append(new Return(x, !noSafepoints()));
+        append(new Return(x, !noSafepoints(), graph));
     }
 
     /**
@@ -1038,7 +1037,7 @@
         int lockNumber = locksSize();
         MonitorAddress lockAddress = null;
         if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
-            lockAddress = new MonitorAddress(lockNumber);
+            lockAddress = new MonitorAddress(lockNumber, graph);
             append(lockAddress);
         }
         MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, null, graph);
@@ -1055,7 +1054,7 @@
         }
         MonitorAddress lockAddress = null;
         if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
-            lockAddress = new MonitorAddress(lockNumber);
+            lockAddress = new MonitorAddress(lockNumber, graph);
             append(lockAddress);
         }
         appendWithoutOptimization(new MonitorExit(x, lockAddress, lockNumber, null, graph), bci);
@@ -1088,7 +1087,7 @@
         list.add(blockAt(bci + offset));
         boolean isSafepoint = isBackwards && !noSafepoints();
         FrameState stateBefore = isSafepoint ? curState.immutableCopy(bci()) : null;
-        append(new TableSwitch(ipop(), list, ts.lowKey(), stateBefore, isSafepoint));
+        append(new TableSwitch(ipop(), list, ts.lowKey(), stateBefore, isSafepoint, graph));
     }
 
     void genLookupswitch() {
@@ -1110,7 +1109,7 @@
         list.add(blockAt(bci + offset));
         boolean isSafepoint = isBackwards && !noSafepoints();
         FrameState stateBefore = isSafepoint ? curState.immutableCopy(bci()) : null;
-        append(new LookupSwitch(ipop(), list, keys, stateBefore, isSafepoint));
+        append(new LookupSwitch(ipop(), list, keys, stateBefore, isSafepoint, graph));
     }
 
     /**
@@ -1218,7 +1217,7 @@
         int index = 0;
         if (!isStatic(method.accessFlags())) {
             // add the receiver and assume it is non null
-            Local local = new Local(method.holder().kind(), index);
+            Local local = new Local(method.holder().kind(), index, graph);
             local.setFlag(Value.Flag.NonNull, true);
             local.setDeclaredType(method.holder());
             state.storeLocal(index, local);
@@ -1230,7 +1229,7 @@
         for (int i = 0; i < max; i++) {
             RiType type = sig.argumentTypeAt(i, accessingClass);
             CiKind kind = type.kind().stackKind();
-            Local local = new Local(kind, index);
+            Local local = new Local(kind, index, graph);
             if (type.isResolved()) {
                 local.setDeclaredType(type);
             }
@@ -1262,7 +1261,7 @@
         curState = syncHandler.stateBefore().copy();
 
         int bci = Instruction.SYNCHRONIZATION_ENTRY_BCI;
-        Value exception = appendWithoutOptimization(new ExceptionObject(curState.immutableCopy(bci)), bci);
+        Value exception = appendWithoutOptimization(new ExceptionObject(curState.immutableCopy(bci), graph), bci);
 
         assert lock != null;
         assert curState.locksSize() > 0 && curState.lockAt(locksSize() - 1) == lock;
@@ -1327,7 +1326,7 @@
             }
             if (nextBlock != null && nextBlock != block) {
                 // we fell through to the next block, add a goto and break
-                end = new Goto(nextBlock, null, false);
+                end = new Goto(nextBlock, null, false, graph);
                 lastInstr = lastInstr.appendNext(end, prevBCI);
                 break;
             }
@@ -1337,7 +1336,7 @@
             // push an exception object onto the stack if we are parsing an exception handler
             if (pushException) {
                 FrameState stateBefore = curState.immutableCopy(bci());
-                apush(append(new ExceptionObject(stateBefore)));
+                apush(append(new ExceptionObject(stateBefore, graph)));
                 pushException = false;
             }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Fri May 06 16:21:10 2011 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.ir.*;
@@ -61,6 +62,8 @@
      */
     private List<BlockBegin> orderedBlocks;
 
+    private final Graph graph = new Graph();
+
     /**
      * Creates a new IR instance for the specified compilation.
      * @param compilation the compilation
@@ -93,7 +96,7 @@
 
     private void buildGraph() {
         // Graph builder must set the startBlock and the osrEntryBlock
-        new GraphBuilder(compilation, this).build();
+        new GraphBuilder(compilation, this, graph).build();
         assert startBlock != null;
         verifyAndPrint("After graph building");
 
@@ -173,12 +176,12 @@
         }
 
         // create new successor and mark it for special block order treatment
-        BlockBegin newSucc = new BlockBegin(bci, nextBlockNumber());
+        BlockBegin newSucc = new BlockBegin(bci, nextBlockNumber(), graph);
 
         newSucc.setCriticalEdgeSplit(true);
 
         // This goto is not a safepoint.
-        Goto e = new Goto(target, null, false);
+        Goto e = new Goto(target, null, false, graph);
         newSucc.appendNext(e, bci);
         newSucc.setEnd(e);
         // setup states
@@ -226,8 +229,8 @@
             newBlock.addPredecessor(pred);
         }
         // this block is now disconnected; remove all its incoming and outgoing edges
-        oldBlock.blockPredecessors().clear();
-        oldBlock.end().blockSuccessors().clear();
+//        oldBlock.blockPredecessors().clear();
+//        oldBlock.end().blockSuccessors().clear();
     }
 
     /**
@@ -273,4 +276,8 @@
     public final int maxLocks() {
         return maxLocks;
     }
+
+    public Graph graph() {
+        return graph;
+    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Base.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Base.java	Fri May 06 16:21:10 2011 +0200
@@ -22,25 +22,28 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.cri.ci.*;
 
 /**
  * The {@code Base} instruction represents the end of the entry block of the procedure that has
  * both the standard entry and the OSR entry as successors.
- *
- * @author Ben L. Titzer
  */
 public final class Base extends BlockEnd {
 
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     /**
      * Constructs a new Base instruction.
      * @param standardEntry the standard entrypoint block
+     * @param graph
      */
-    public Base(BlockBegin standardEntry) {
-        super(CiKind.Illegal, null, false);
+    public Base(BlockBegin standardEntry, Graph graph) {
+        super(CiKind.Illegal, null, false, 1, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         assert standardEntry.isStandardEntry();
-        successors.add(standardEntry);
+        setBlockSuccessor(0, standardEntry);
     }
 
     /**
@@ -56,7 +59,7 @@
      * @return the OSR entrypoint bock, if it exists; {@code null} otherwise
      */
     public BlockBegin osrEntry() {
-        return successors.size() < 2 ? null : successors.get(0);
+        return blockSuccessorCount() < 2 ? null : blockSuccessor(0);
     }
 
     @Override
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java	Fri May 06 16:21:10 2011 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.*;
 import com.sun.c1x.asm.*;
 import com.sun.c1x.debug.*;
@@ -37,10 +38,12 @@
  * Denotes the beginning of a basic block, and holds information
  * about the basic block, including the successor and
  * predecessor blocks, exception handlers, liveness information, etc.
- *
- * @author Ben L. Titzer
  */
 public final class BlockBegin extends Instruction {
+
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     private static final List<BlockBegin> NO_HANDLERS = Collections.emptyList();
 
     /**
@@ -103,9 +106,10 @@
      * Constructs a new BlockBegin at the specified bytecode index.
      * @param bci the bytecode index of the start
      * @param blockID the ID of the block
+     * @param graph
      */
-    public BlockBegin(int bci, int blockID) {
-        super(CiKind.Illegal);
+    public BlockBegin(int bci, int blockID, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.blockID = blockID;
         depthFirstNumber = -1;
         linearScanNumber = -1;
@@ -439,7 +443,7 @@
                 throw new CiBailout("jsr/ret too complicated");
             }
 
-            existingState.merge(this, newState);
+            existingState.merge(this, newState, graph());
         }
     }
 
@@ -461,13 +465,13 @@
         int stackSize = newState.stackSize();
         for (int i = 0; i < stackSize; i++) {
             // always insert phis for the stack
-            newState.setupPhiForStack(this, i);
+            newState.setupPhiForStack(this, i, graph());
         }
         int localsSize = newState.localsSize();
         for (int i = 0; i < localsSize; i++) {
             Value x = newState.localAt(i);
             if (x != null) {
-                newState.setupPhiForLocal(this, i);
+                newState.setupPhiForLocal(this, i, graph());
             }
         }
     }
@@ -609,7 +613,7 @@
      * @return the number of successors
      */
     public int numberOfSux() {
-        return end.successors.size();
+        return end.blockSuccessorCount();
     }
 
     /**
@@ -618,7 +622,7 @@
      * @return the successor
      */
     public BlockBegin suxAt(int i) {
-        return end.successors.get(i);
+        return end.blockSuccessor(i);
     }
 
     /**
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java	Fri May 06 16:21:10 2011 +0200
@@ -24,7 +24,7 @@
 
 import java.util.*;
 
-import com.sun.c1x.util.*;
+import com.oracle.graal.graph.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
 
@@ -34,8 +34,38 @@
  */
 public abstract class BlockEnd extends Instruction {
 
+    private static final int INPUT_COUNT = 0;
+
+    private final int blockSuccessorCount;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + blockSuccessorCount;
+    }
+
+    /**
+     * The list of instructions that produce input for this instruction.
+     */
+    public BlockBegin blockSuccessor(int index) {
+        assert index >= 0 && index < blockSuccessorCount;
+        return (BlockBegin) successors().get(super.successorCount() + index);
+    }
+
+    public BlockBegin setBlockSuccessor(int index, BlockBegin n) {
+        assert index >= 0 && index < blockSuccessorCount;
+        return (BlockBegin) successors().set(super.successorCount() + index, n);
+    }
+
+    public int blockSuccessorCount() {
+        return blockSuccessorCount;
+    }
+
     BlockBegin begin;
-    final List<BlockBegin> successors;
     FrameState stateAfter;
     boolean isSafepoint;
 
@@ -46,15 +76,22 @@
      * @param isSafepoint {@code true} if this instruction is a safepoint instruction
      * @param successors the list of successor blocks. If {@code null}, a new one will be created.
      */
-    public BlockEnd(CiKind kind, FrameState stateAfter, boolean isSafepoint, List<BlockBegin> successors) {
-        super(kind);
-        this.successors = successors == null ? new ArrayList<BlockBegin>(2) : successors;
+    public BlockEnd(CiKind kind, FrameState stateAfter, boolean isSafepoint, List<BlockBegin> blockSuccessors, int inputCount, int successorCount, Graph graph) {
+        this(kind, stateAfter, isSafepoint, blockSuccessors.size(), inputCount, successorCount, graph);
+        for (int i = 0; i < blockSuccessors.size(); i++) {
+            setBlockSuccessor(i, blockSuccessors.get(i));
+        }
+    }
+
+    public BlockEnd(CiKind kind, FrameState stateAfter, boolean isSafepoint, int blockSuccessorCount, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + blockSuccessorCount, graph);
+        this.blockSuccessorCount = blockSuccessorCount;
         setStateAfter(stateAfter);
         this.isSafepoint = isSafepoint;
     }
 
-    public BlockEnd(CiKind kind, FrameState stateAfter, boolean isSafepoint) {
-        this(kind, stateAfter, isSafepoint, null);
+    public BlockEnd(CiKind kind, FrameState stateAfter, boolean isSafepoint, Graph graph) {
+        this(kind, stateAfter, isSafepoint, 2, 0, 0, graph);
     }
 
     /**
@@ -103,7 +140,11 @@
      */
     public void substituteSuccessor(BlockBegin oldSucc, BlockBegin newSucc) {
         assert newSucc != null;
-        Util.replaceAllInList(oldSucc, newSucc, successors);
+        for (int i = 0; i < blockSuccessorCount; i++) {
+            if (blockSuccessor(i) == oldSucc) {
+                setBlockSuccessor(i, newSucc);
+            }
+        }
     }
 
     /**
@@ -111,7 +152,7 @@
      * @return the default successor
      */
     public BlockBegin defaultSuccessor() {
-        return successors.get(successors.size() - 1);
+        return blockSuccessor(blockSuccessorCount - 1);
     }
 
     /**
@@ -121,9 +162,8 @@
      * @return the index of the block in the list if found; <code>-1</code> otherwise
      */
     public int successorIndex(BlockBegin b) {
-        final int max = successors.size();
-        for (int i = 0; i < max; i++) {
-            if (successors.get(i) == b) {
+        for (int i = 0; i < blockSuccessorCount; i++) {
+            if (blockSuccessor(i) == b) {
                 return i;
             }
         }
@@ -135,15 +175,8 @@
      * @return the successor list
      */
     public List<BlockBegin> blockSuccessors() {
-        return successors;
+        List<BlockBegin> list = (List) successors().subList(super.successorCount(), super.successorCount() + blockSuccessorCount);
+        return Collections.unmodifiableList(list);
     }
 
-    /**
-     * Gets the successor at a specified index.
-     * @param index the index of the successor
-     * @return the successor
-     */
-    public BlockBegin suxAt(int index) {
-        return successors.get(index);
-    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/CheckCast.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/CheckCast.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.util.*;
 import com.sun.c1x.value.*;
@@ -31,19 +32,21 @@
 
 /**
  * The {@code CheckCast} instruction represents a {@link Bytecodes#CHECKCAST}.
- *
- * @author Ben L. Titzer
  */
 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
      * @param object the instruction producing the object
      * @param stateBefore the state before the cast
+     * @param graph
      */
-    public CheckCast(RiType targetClass, Value targetClassInstruction, Value object, FrameState stateBefore) {
-        super(targetClass, targetClassInstruction, object, CiKind.Object, stateBefore);
+    public CheckCast(RiType targetClass, Value targetClassInstruction, Value object, FrameState stateBefore, Graph graph) {
+        super(targetClass, targetClassInstruction, object, CiKind.Object, stateBefore, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         initFlag(Flag.NonNull, object.isNonNull());
     }
 
@@ -72,14 +75,14 @@
 
     @Override
     public int valueNumber() {
-        return targetClass.isResolved() ? Util.hash1(Bytecodes.CHECKCAST, object) : 0;
+        return targetClass.isResolved() ? Util.hash1(Bytecodes.CHECKCAST, object()) : 0;
     }
 
     @Override
     public boolean valueEqual(Instruction i) {
         if (i instanceof CheckCast) {
             CheckCast o = (CheckCast) i;
-            return targetClass == o.targetClass && object == o.object;
+            return targetClass == o.targetClass && object() == o.object();
         }
         return false;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ExceptionObject.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ExceptionObject.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
@@ -31,6 +32,9 @@
  */
 public final class ExceptionObject extends Instruction {
 
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     /**
      * Debug info is required if safepoints are placed at exception handlers.
      */
@@ -39,9 +43,10 @@
     /**
      * Constructs a new ExceptionObject instruction.
      * @param stateBefore TODO
+     * @param graph
      */
-    public ExceptionObject(FrameState stateBefore) {
-        super(CiKind.Object);
+    public ExceptionObject(FrameState stateBefore, Graph graph) {
+        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setFlag(Flag.NonNull);
         this.stateBefore = stateBefore;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Goto.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Goto.java	Fri May 06 16:21:10 2011 +0200
@@ -22,26 +22,29 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
 
 /**
  * The {@code Goto} instruction represents the end of a block with an unconditional jump to another block.
- *
- * @author Ben L. Titzer
  */
 public final class Goto extends BlockEnd {
 
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     /**
      * Constructs a new Goto instruction.
      * @param succ the successor block of the goto
      * @param stateAfter the frame state at the end of this block
      * @param isSafepoint {@code true} if the goto should be considered a safepoint (e.g. backward branch)
+     * @param graph
      */
-    public Goto(BlockBegin succ, FrameState stateAfter, boolean isSafepoint) {
-        super(CiKind.Illegal, stateAfter, isSafepoint);
-        successors.add(succ);
+    public Goto(BlockBegin succ, FrameState stateAfter, boolean isSafepoint, Graph graph) {
+        super(CiKind.Illegal, stateAfter, isSafepoint, 1, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setBlockSuccessor(0, succ);
     }
 
     @Override
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/If.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/If.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.util.*;
 import com.sun.c1x.value.*;
@@ -30,13 +31,47 @@
 /**
  * The {@code If} instruction represents a branch that can go one of two directions
  * depending on the outcome of a comparison.
- *
- * @author Ben L. Titzer
  */
 public final class If extends BlockEnd {
 
-    Value x;
-    Value y;
+    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;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The instruction that produces the first input to this comparison.
+     */
+     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);
+    }
+
+    /**
+     * 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);
+    }
+
     Condition condition;
     boolean unorderedIsTrue;
 
@@ -44,38 +79,22 @@
      * Constructs a new If instruction.
      * @param x the instruction producing the first input to the instruction
      * @param cond the condition (comparison operation)
-     * @param unorderedIsTrue {@code true} if unordered is treated as true (floating point operations)
      * @param y the instruction that produces the second input to this instruction
      * @param trueSucc the block representing the true successor
      * @param falseSucc the block representing the false successor
      * @param stateAfter the state before the branch but after the input values have been popped
      * @param isSafepoint {@code true} if this branch should be considered a safepoint
+     * @param graph
      */
     public If(Value x, Condition cond, Value y,
-              BlockBegin trueSucc, BlockBegin falseSucc, FrameState stateAfter, boolean isSafepoint) {
-        super(CiKind.Illegal, stateAfter, isSafepoint);
-        this.x = x;
-        this.y = y;
-        condition = cond;
+              BlockBegin trueSucc, BlockBegin falseSucc, FrameState stateAfter, boolean isSafepoint, Graph graph) {
+        super(CiKind.Illegal, stateAfter, isSafepoint, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         assert Util.archKindsEqual(x, y);
-        successors.add(trueSucc);
-        successors.add(falseSucc);
-    }
-
-    /**
-     * Gets the instruction that produces the first input to this comparison.
-     * @return the instruction producing the first input
-     */
-    public Value x() {
-        return x;
-    }
-
-    /**
-     * Gets the instruction that produces the second input to this comparison.
-     * @return the instruction producing the second input
-     */
-    public Value y() {
-        return y;
+        condition = cond;
+        setX(x);
+        setY(y);
+        setBlockSuccessor(0, trueSucc);
+        setBlockSuccessor(1, falseSucc);
     }
 
     /**
@@ -99,7 +118,7 @@
      * @return the true successor
      */
     public BlockBegin trueSuccessor() {
-        return successors.get(0);
+        return blockSuccessor(0);
     }
 
     /**
@@ -107,7 +126,7 @@
      * @return the false successor
      */
     public BlockBegin falseSuccessor() {
-        return successors.get(1);
+        return blockSuccessor(1);
     }
 
     /**
@@ -116,7 +135,7 @@
      * @return the corresponding successor
      */
     public BlockBegin successor(boolean istrue) {
-        return successors.get(istrue ? 0 : 1);
+        return blockSuccessor(istrue ? 0 : 1);
     }
 
     /**
@@ -133,9 +152,9 @@
      */
     public void swapOperands() {
         condition = condition.mirror();
-        Value t = x;
-        x = y;
-        y = t;
+        Value t = x();
+        setX(y());
+        setY(t);
     }
 
     /**
@@ -145,16 +164,10 @@
     public void swapSuccessors() {
         unorderedIsTrue = !unorderedIsTrue;
         condition = condition.negate();
-        BlockBegin t = successors.get(0);
-        BlockBegin f = successors.get(1);
-        successors.set(0, f);
-        successors.set(1, t);
-    }
-
-    @Override
-    public void inputValuesDo(ValueClosure closure) {
-        x = closure.apply(x);
-        y = closure.apply(y);
+        BlockBegin t = blockSuccessor(0);
+        BlockBegin f = blockSuccessor(1);
+        setBlockSuccessor(0, f);
+        setBlockSuccessor(1, t);
     }
 
     @Override
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/InstanceOf.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/InstanceOf.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.util.*;
 import com.sun.c1x.value.*;
@@ -31,19 +32,21 @@
 
 /**
  * The {@code InstanceOf} instruction represents an instanceof test.
- *
- * @author Ben L. Titzer
  */
 public final class InstanceOf extends TypeCheck {
 
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     /**
      * Constructs a new InstanceOf instruction.
      * @param targetClass the target class of the instanceof check
      * @param object the instruction producing the object input to this instruction
      * @param stateBefore the state before this instruction
+     * @param graph
      */
-    public InstanceOf(RiType targetClass, Value targetClassInstruction, Value object, FrameState stateBefore) {
-        super(targetClass, targetClassInstruction, object, CiKind.Int, stateBefore);
+    public InstanceOf(RiType targetClass, Value targetClassInstruction, Value object, FrameState stateBefore, Graph graph) {
+        super(targetClass, targetClassInstruction, object, CiKind.Int, stateBefore, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
     @Override
@@ -53,14 +56,14 @@
 
     @Override
     public int valueNumber() {
-        return Util.hash1(Bytecodes.INSTANCEOF, object);
+        return Util.hash1(Bytecodes.INSTANCEOF, object());
     }
 
     @Override
     public boolean valueEqual(Instruction i) {
         if (i instanceof InstanceOf) {
             InstanceOf o = (InstanceOf) i;
-            return targetClass == o.targetClass && object == o.object;
+            return targetClass == o.targetClass && object() == o.object();
         }
         return false;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java	Fri May 06 16:21:10 2011 +0200
@@ -97,10 +97,6 @@
         C1XMetrics.HIRInstructions++;
     }
 
-    public Instruction(CiKind kind) {
-        this(kind, 0, 0, null);
-    }
-
     /**
      * Gets the bytecode index of this instruction.
      * @return the bytecode index of this instruction
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Local.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Local.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -29,16 +30,17 @@
 /**
  * The {@code Local} instruction is a placeholder for an incoming argument
  * to a function call.
- *
- * @author Ben L. Titzer
  */
 public final class Local extends Value {
 
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     private final int javaIndex;
     private RiType declaredType;
 
-    public Local(CiKind kind, int javaIndex) {
-        super(kind);
+    public Local(CiKind kind, int javaIndex, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.javaIndex = javaIndex;
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/LookupSwitch.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LookupSwitch.java	Fri May 06 16:21:10 2011 +0200
@@ -26,17 +26,19 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 
 /**
  * The {@code LookupSwitch} instruction represents a lookup switch bytecode, which has a sorted
  * array of key values.
- *
- * @author Ben L. Titzer
  */
 public final class LookupSwitch extends Switch {
 
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     final int[] keys;
 
     /**
@@ -46,9 +48,10 @@
      * @param keys the list of keys, sorted
      * @param stateBefore the state before the switch
      * @param isSafepoint {@code true} if this instruction is a safepoint
+     * @param graph
      */
-    public LookupSwitch(Value value, List<BlockBegin> successors, int[] keys, FrameState stateBefore, boolean isSafepoint) {
-        super(value, successors, stateBefore, isSafepoint);
+    public LookupSwitch(Value value, List<BlockBegin> successors, int[] keys, FrameState stateBefore, boolean isSafepoint, Graph graph) {
+        super(value, successors, stateBefore, isSafepoint, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.keys = keys;
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorAddress.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorAddress.java	Fri May 06 16:21:10 2011 +0200
@@ -22,20 +22,22 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.cri.ci.*;
 
 /**
  * Instruction that is used to refer to the address of an on-stack monitor.
- *
- * @author Lukas Stadler
  */
 public final class MonitorAddress extends Instruction {
 
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     private int monitor;
 
-    public MonitorAddress(int monitor) {
-        super(CiKind.Word);
+    public MonitorAddress(int monitor, Graph graph) {
+        super(CiKind.Word, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.monitor = monitor;
         setFlag(Flag.NonNull);
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NewArray.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NewArray.java	Fri May 06 16:21:10 2011 +0200
@@ -22,43 +22,53 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
 
 /**
  * The {@code NewArray} class is the base of all instructions that allocate arrays.
- *
- * @author Ben L. Titzer
  */
 public abstract class NewArray extends StateSplit {
 
-    Value length;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_LENGTH = 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;
+    }
+
+    /**
+     * 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);
+    }
 
     /**
      * Constructs a new NewArray instruction.
      * @param length the instruction that produces the length for this allocation
      * @param stateBefore the state before the allocation
+     * @param inputCount
+     * @param successorCount
+     * @param graph
      */
-    NewArray(Value length, FrameState stateBefore) {
-        super(CiKind.Object, stateBefore);
-        this.length = length;
+    NewArray(Value length, FrameState stateBefore, int inputCount, int successorCount, Graph graph) {
+        super(CiKind.Object, stateBefore, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
         setFlag(Flag.NonNull);
+        setLength(length);
     }
 
-    /**
-     * Gets the instruction that produces the length of this array.
-     * @return the instruction that produces the length
-     */
-    public Value length() {
-        return length;
-    }
-
-    /**
-     * Applies the specified closure to all input values of this instruction.
-     * @param closure the closure to apply
-     */
-    @Override
-    public void inputValuesDo(ValueClosure closure) {
-        length = closure.apply(length);
-    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NewInstance.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NewInstance.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
@@ -29,11 +30,12 @@
 
 /**
  * The {@code NewInstance} instruction represents the allocation of an instance class object.
- *
- * @author Ben L. Titzer
  */
 public final class NewInstance extends StateSplit {
 
+    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;
@@ -43,9 +45,10 @@
      * @param type the class being allocated
      * @param cpi the constant pool index
      * @param stateBefore the state before executing this instruction
+     * @param graph
      */
-    public NewInstance(RiType type, int cpi, RiConstantPool constantPool, FrameState stateBefore) {
-        super(CiKind.Object, stateBefore);
+    public NewInstance(RiType type, int cpi, RiConstantPool constantPool, FrameState stateBefore, Graph graph) {
+        super(CiKind.Object, stateBefore, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.instanceClass = type;
         this.cpi = cpi;
         this.constantPool = constantPool;
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NewMultiArray.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NewMultiArray.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
@@ -30,12 +31,44 @@
 /**
  * The {@code NewMultiArray} instruction represents an allocation of a multi-dimensional object
  * array.
- *
- * @author Ben L. Titzer
  */
 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;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The list of instructions which produce input for this instruction.
+     */
+    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);
+    }
+
+    /**
+     * The rank of the array allocated by this instruction, i.e. how many array dimensions.
+     */
+    public int dimensionCount() {
+        return dimensionCount;
+    }
+
     public final RiType elementKind;
-    final Value[] dimensions;
     public final int cpi;
     public final RiConstantPool constantPool;
 
@@ -46,35 +79,17 @@
      * @param stateBefore the state before this instruction
      * @param cpi the constant pool index for resolution
      * @param riConstantPool the constant pool for resolution
+     * @param graph
      */
-    public NewMultiArray(RiType elementKind, Value[] dimensions, FrameState stateBefore, int cpi, RiConstantPool riConstantPool) {
-        super(null, stateBefore);
+    public NewMultiArray(RiType elementKind, Value[] dimensions, FrameState stateBefore, int cpi, RiConstantPool riConstantPool, Graph graph) {
+        super(null, stateBefore, dimensions.length, SUCCESSOR_COUNT, graph);
         this.constantPool = riConstantPool;
         this.elementKind = elementKind;
-        this.dimensions = dimensions;
         this.cpi = cpi;
-    }
-
-    /**
-     * Gets the list of instructions which produce input for this instruction.
-     * @return the list of instructions which produce input
-     */
-    public Value[] dimensions() {
-        return dimensions;
-    }
 
-    /**
-     * Gets the rank of the array allocated by this instruction, i.e. how many array dimensions.
-     * @return the rank of the array allocated
-     */
-    public int rank() {
-        return dimensions.length;
-    }
-
-    @Override
-    public void inputValuesDo(ValueClosure closure) {
+        this.dimensionCount = dimensions.length;
         for (int i = 0; i < dimensions.length; i++) {
-            dimensions[i] = closure.apply(dimensions[i]);
+            setDimension(i, dimensions[i]);
         }
     }
 
@@ -94,12 +109,11 @@
     @Override
     public void print(LogStream out) {
         out.print("new multi array [");
-        final Value[] dimensions = dimensions();
-        for (int i = 0; i < dimensions.length; i++) {
+        for (int i = 0; i < dimensionCount; i++) {
           if (i > 0) {
               out.print(", ");
           }
-          out.print(dimensions[i]);
+          out.print(dimension(i));
         }
         out.print("] ").print(CiUtil.toJavaName(elementKind));
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NewObjectArray.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NewObjectArray.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
@@ -29,11 +30,12 @@
 
 /**
  * The {@code NewObjectArray} instruction represents an allocation of an object array.
- *
- * @author Ben L. Titzer
  */
 public final class NewObjectArray extends NewArray {
 
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     final RiType elementClass;
 
     /**
@@ -41,9 +43,10 @@
      * @param elementClass the class of elements in this array
      * @param length the instruction producing the length of the array
      * @param stateBefore the state before the allocation
+     * @param graph
      */
-    public NewObjectArray(RiType elementClass, Value length, FrameState stateBefore) {
-        super(length, stateBefore);
+    public NewObjectArray(RiType elementClass, Value length, FrameState stateBefore, Graph graph) {
+        super(length, stateBefore, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.elementClass = elementClass;
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NewTypeArray.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NewTypeArray.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
@@ -29,15 +30,16 @@
 
 /**
  * The {@code NewTypeArray} class definition.
- *
- * @author Ben L. Titzer
  */
 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, FrameState stateBefore) {
-        super(length, stateBefore);
+    public NewTypeArray(Value length, RiType elementType, FrameState stateBefore, Graph graph) {
+        super(length, stateBefore, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.elementType = elementType;
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NullCheck.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NullCheck.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.util.*;
 import com.sun.c1x.value.*;
@@ -33,30 +34,42 @@
  */
 public final class NullCheck extends StateSplit {
 
-    Value object;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 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;
+    }
+
+    /**
+     * 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);
+    }
 
     /**
      * Constructs a new NullCheck instruction.
-     * @param obj the instruction producing the object to check against null
+     * @param object the instruction producing the object to check against null
      * @param stateBefore the state before executing the null check
+     * @param graph
      */
-    public NullCheck(Value obj, FrameState stateBefore) {
-        super(obj.kind, stateBefore);
-        this.object = obj;
+    public NullCheck(Value object, FrameState stateBefore, Graph graph) {
+        super(object.kind, stateBefore, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setFlag(Flag.NonNull);
-    }
-
-    /**
-     * Gets the instruction that produces the object tested against null.
-     * @return the instruction producing the object
-     */
-    public Value object() {
-        return object;
-    }
-
-    @Override
-    public void inputValuesDo(ValueClosure closure) {
-        object = closure.apply(object);
+        setObject(object);
     }
 
     @Override
@@ -66,14 +79,14 @@
 
     @Override
     public int valueNumber() {
-        return Util.hash1(Bytecodes.IFNONNULL, object);
+        return Util.hash1(Bytecodes.IFNONNULL, object());
     }
 
     @Override
     public boolean valueEqual(Instruction i) {
         if (i instanceof NullCheck) {
             NullCheck o = (NullCheck) i;
-            return object == o.object;
+            return object() == o.object();
         }
         return false;
     }
@@ -81,13 +94,13 @@
     @Override
     public RiType declaredType() {
         // null check does not alter the type of the object
-        return object.declaredType();
+        return object().declaredType();
     }
 
     @Override
     public RiType exactType() {
         // null check does not alter the type of the object
-        return object.exactType();
+        return object().exactType();
     }
 
     @Override
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
@@ -29,12 +30,36 @@
 /**
  * The {@code Phi} instruction represents the merging of dataflow
  * in the instruction graph. It refers to a join block and a variable.
- *
- * @author Ben L. Titzer
  */
 public final class Phi extends Value {
 
-    private final BlockBegin block;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_BLOCK = 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;
+    }
+
+    /**
+     * The join block for this phi.
+     */
+     @Override
+    public BlockBegin block() {
+        return (BlockBegin) inputs().get(super.inputCount() + INPUT_BLOCK);
+    }
+
+    public BlockBegin setBlock(Value n) {
+        return (BlockBegin) inputs().set(super.inputCount() + INPUT_BLOCK, n);
+    }
+
     private final int index;
 
     /**
@@ -42,20 +67,12 @@
      * @param kind the type of the variable
      * @param block the join point
      * @param index the index into the stack (if < 0) or local variables
+     * @param graph
      */
-    public Phi(CiKind kind, BlockBegin block, int index) {
-        super(kind);
-        this.block = block;
+    public Phi(CiKind kind, BlockBegin block, int index, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.index = index;
-    }
-
-    /**
-     * Get the join block for this phi.
-     * @return the join block of this phi
-     */
-    @Override
-    public BlockBegin block() {
-        return block;
+        setBlock(block);
     }
 
     /**
@@ -100,10 +117,10 @@
      */
     public Value inputAt(int i) {
         FrameState state;
-        if (block.isExceptionEntry()) {
-            state = block.exceptionHandlerStates().get(i);
+        if (block().isExceptionEntry()) {
+            state = block().exceptionHandlerStates().get(i);
         } else {
-            state = block.blockPredecessors().get(i).end().stateAfter();
+            state = block().blockPredecessors().get(i).end().stateAfter();
         }
         return inputIn(state);
     }
@@ -126,10 +143,10 @@
      * @return the number of inputs in this phi
      */
     public int phiInputCount() {
-        if (block.isExceptionEntry()) {
-            return block.exceptionHandlerStates().size();
+        if (block().isExceptionEntry()) {
+            return block().exceptionHandlerStates().size();
         } else {
-            return block.blockPredecessors().size();
+            return block().blockPredecessors().size();
         }
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/RegisterFinalizer.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/RegisterFinalizer.java	Fri May 06 16:21:10 2011 +0200
@@ -22,27 +22,45 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
 
+/**
+ * This instruction is used to perform the finalizer registration at the end of the java.lang.Object constructor.
+ */
 public class RegisterFinalizer extends StateSplit {
 
-    private Value object;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_OBJECT = 0;
 
-    public RegisterFinalizer(Value object, FrameState stateBefore) {
-        super(CiKind.Void, stateBefore);
-        this.object = object;
-    }
+    private static final int SUCCESSOR_COUNT = 0;
 
-    public Value object() {
-        return object;
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
     }
 
     @Override
-    public void inputValuesDo(ValueClosure closure) {
-        object = closure.apply(object);
-        super.inputValuesDo(closure);
+    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 RegisterFinalizer(Value object, FrameState stateBefore, Graph graph) {
+        super(CiKind.Void, stateBefore, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setObject(object);
     }
 
     @Override
@@ -52,6 +70,6 @@
 
     @Override
     public void print(LogStream out) {
-        out.print("register finalizer ").print(object);
+        out.print("register finalizer ").print(object());
     }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ResolveClass.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ResolveClass.java	Fri May 06 16:21:10 2011 +0200
@@ -22,6 +22,7 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
@@ -30,17 +31,17 @@
 /**
  * An instruction that represents the runtime resolution of a Java class object. For example, an
  * ldc of a class constant that is unresolved.
- *
- * @author Ben L. Titzer
- * @author Thomas Wuerthinger
  */
 public final class ResolveClass extends StateSplit {
 
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     public final RiType type;
     public final RiType.Representation portion;
 
-    public ResolveClass(RiType type, RiType.Representation r, FrameState stateBefore) {
-        super(type.getRepresentationKind(r), stateBefore);
+    public ResolveClass(RiType type, RiType.Representation r, FrameState stateBefore, Graph graph) {
+        super(type.getRepresentationKind(r), stateBefore, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.portion = r;
         this.type = type;
         setFlag(Flag.NonNull);
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Return.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Return.java	Fri May 06 16:21:10 2011 +0200
@@ -22,42 +22,51 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.cri.ci.*;
 
 /**
  * The {@code Return} class definition.
- *
- * @author Ben L. Titzer
  */
 public final class Return extends BlockEnd {
 
-    Value result;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_RESULT = 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;
+    }
+
+    /**
+     * 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);
+    }
 
     /**
      * Constructs a new Return instruction.
      * @param result the instruction producing the result for this return; {@code null} if this
      * is a void return
      * @param isSafepoint {@code true} if this instruction is a safepoint instruction
-     */
-    public Return(Value result, boolean isSafepoint) {
-        super(result == null ? CiKind.Void : result.kind, null, isSafepoint);
-        this.result = result;
-    }
-
-    /**
-     * Gets the instruction that produces the result for the return.
-     * @return the instruction producing the result
+     * @param graph
      */
-    public Value result() {
-        return result;
-    }
-
-    @Override
-    public void inputValuesDo(ValueClosure closure) {
-        if (result != null) {
-            result = closure.apply(result);
-        }
+    public Return(Value result, boolean isSafepoint, Graph graph) {
+        super(result == null ? CiKind.Void : result.kind, null, isSafepoint, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setResult(result);
     }
 
     @Override
@@ -67,10 +76,10 @@
 
     @Override
     public void print(LogStream out) {
-        if (result == null) {
+        if (result() == null) {
             out.print("return");
         } else {
-            out.print(kind.typeChar).print("return ").print(result);
+            out.print(kind.typeChar).print("return ").print(result());
         }
     }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java	Fri May 06 16:21:10 2011 +0200
@@ -54,10 +54,6 @@
         this.stateBefore = stateBefore;
     }
 
-    public StateSplit(CiKind kind, FrameState stateBefore) {
-        this(kind, stateBefore, 0, 0, null);
-    }
-
     @Override
     public boolean canTrap() {
         return stateBefore != null;
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Switch.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Switch.java	Fri May 06 16:21:10 2011 +0200
@@ -24,17 +24,40 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
 
 /**
  * The {@code Switch} class is the base of both lookup and table switches.
- *
- * @author Ben L. Titzer
  */
 public abstract class Switch extends BlockEnd {
 
-    Value value;
+    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;
+    }
+
+    @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);
+    }
 
     /**
      * Constructs a new Switch.
@@ -42,18 +65,11 @@
      * @param successors the list of successors of this switch
      * @param stateBefore the state before the switch
      * @param isSafepoint {@code true} if this switch is a safepoint
+     * @param graph
      */
-    public Switch(Value value, List<BlockBegin> successors, FrameState stateBefore, boolean isSafepoint) {
-        super(CiKind.Illegal, stateBefore, isSafepoint, successors);
-        this.value = value;
-    }
-
-    /**
-     * Gets the instruction that provides the input value to this switch.
-     * @return the instruction producing the input value
-     */
-    public Value value() {
-        return value;
+    public Switch(Value value, List<BlockBegin> successors, FrameState stateBefore, boolean isSafepoint, int inputCount, int successorCount, Graph graph) {
+        super(CiKind.Illegal, stateBefore, isSafepoint, successors, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        setValue(value);
     }
 
     /**
@@ -61,15 +77,7 @@
      * @return the number of cases
      */
     public int numberOfCases() {
-        return successors.size() - 1;
+        return blockSuccessorCount() - 1;
     }
 
-    /**
-     * Iterates over the inputs to this instruction.
-     * @param closure the closure to apply
-     */
-    @Override
-    public void inputValuesDo(ValueClosure closure) {
-        value = closure.apply(value);
-    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/TableSwitch.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/TableSwitch.java	Fri May 06 16:21:10 2011 +0200
@@ -26,16 +26,18 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 
 /**
  * The {@code TableSwitch} instruction represents a table switch.
- *
- * @author Ben L. Titzer
  */
 public final class TableSwitch extends Switch {
 
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
     final int lowKey;
 
     /**
@@ -45,9 +47,10 @@
      * @param lowKey the lowest integer key in the table
      * @param stateBefore the state before the switch
      * @param isSafepoint {@code true} if this instruction is a safepoint
+     * @param graph
      */
-    public TableSwitch(Value value, List<BlockBegin> successors, int lowKey, FrameState stateBefore, boolean isSafepoint) {
-        super(value, successors, stateBefore, isSafepoint);
+    public TableSwitch(Value value, List<BlockBegin> successors, int lowKey, FrameState stateBefore, boolean isSafepoint, Graph graph) {
+        super(value, successors, stateBefore, isSafepoint, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.lowKey = lowKey;
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java	Fri May 06 16:21:10 2011 +0200
@@ -22,18 +22,41 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
 
 /**
  * The {@code Throw} instruction represents a throw of an exception.
- *
- * @author Ben L. Titzer
  */
 public final class Throw extends BlockEnd {
 
-    Value exception;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_EXCEPTION = 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;
+    }
+
+    /**
+     * The instruction which produces the exception to throw.
+     */
+     public Value exception() {
+        return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION);
+    }
+
+    public Value setException(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
+    }
 
     FrameState stateBefore;
 
@@ -42,19 +65,12 @@
      * @param exception the instruction that generates the exception to throw
      * @param stateAfter the state before the exception is thrown but after the exception object has been popped
      * @param isSafepoint {@code true} if this instruction is a safepoint instruction
+     * @param graph
      */
-    public Throw(Value exception, FrameState stateAfter, boolean isSafepoint) {
-        super(CiKind.Illegal, null, isSafepoint);
+    public Throw(Value exception, FrameState stateAfter, boolean isSafepoint, Graph graph) {
+        super(CiKind.Illegal, null, isSafepoint, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.stateBefore = stateAfter;
-        this.exception = exception;
-    }
-
-    /**
-     * Gets the instruction which produces the exception to throw.
-     * @return the instruction producing the exception
-     */
-    public Value exception() {
-        return exception;
+        setException(exception);
     }
 
     /**
@@ -76,11 +92,6 @@
     }
 
     @Override
-    public void inputValuesDo(ValueClosure closure) {
-        exception = closure.apply(exception);
-    }
-
-    @Override
     public void accept(ValueVisitor v) {
         v.visitThrow(this);
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/TypeCheck.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/TypeCheck.java	Fri May 06 16:21:10 2011 +0200
@@ -22,20 +22,55 @@
  */
 package com.sun.c1x.ir;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
 /**
  * The {@code TypeCheck} instruction is the base class of casts and instanceof tests.
- *
- * @author Ben L. Titzer
  */
 public abstract class TypeCheck extends StateSplit {
 
+    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;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * 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);
+    }
+
+    /**
+     * 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 setTargetClassInstruction(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_TARGET_CLASS_INSTRUCTION, n);
+    }
+
     final RiType targetClass;
-    public Value targetClassInstruction;
-    Value object;
 
     /**
      * Creates a new TypeCheck instruction.
@@ -43,20 +78,15 @@
      * @param object the instruction which produces the object
      * @param kind the result type of this instruction
      * @param stateBefore the state before this instruction is executed
+     * @param inputCount
+     * @param successorCount
+     * @param graph
      */
-    public TypeCheck(RiType targetClass, Value targetClassInstruction, Value object, CiKind kind, FrameState stateBefore) {
-        super(kind, stateBefore);
+    public TypeCheck(RiType targetClass, Value targetClassInstruction, Value object, CiKind kind, FrameState stateBefore, int inputCount, int successorCount, Graph graph) {
+        super(kind, stateBefore, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
         this.targetClass = targetClass;
-        this.targetClassInstruction = targetClassInstruction;
-        this.object = object;
-    }
-
-    /**
-     * Gets the instruction that loads the target class object that is used by this checkcast.
-     * @return the target class instruction
-     */
-    public Value targetClassInstruction() {
-        return targetClassInstruction;
+        setObject(object);
+        setTargetClassInstruction(targetClassInstruction);
     }
 
     /**
@@ -68,14 +98,6 @@
     }
 
     /**
-     * Gets the instruction which produces the object input.
-     * @return the instruction producing the object
-     */
-    public Value object() {
-        return object;
-    }
-
-    /**
      * Checks whether the target class of this instruction is loaded.
      * @return {@code true} if the target class is loaded
      */
@@ -83,13 +105,4 @@
         return targetClass != null;
     }
 
-    /**
-     * Iterates over the input values to this instruction.
-     * @param closure the closure to apply
-     */
-    @Override
-    public void inputValuesDo(ValueClosure closure) {
-        object = closure.apply(object);
-        targetClassInstruction = closure.apply(targetClassInstruction);
-    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Value.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Value.java	Fri May 06 16:21:10 2011 +0200
@@ -72,7 +72,7 @@
      * @param graph
      */
     public Value(CiKind kind, int inputCount, int successorCount, Graph graph) {
-        super(inputCount, successorCount, graph == null ? new Graph() : graph);
+        super(inputCount, successorCount, graph);
         assert kind == kind.stackKind() : kind + " != " + kind.stackKind();
         this.kind = kind;
     }
@@ -80,10 +80,6 @@
     ///////////////
     // TODO: remove when Value class changes are completed
 
-    public Value(CiKind kind) {
-        this(kind, 0, 0, null);
-    }
-
     @Override
     public Node copy(Graph into) {
         throw new UnsupportedOperationException();
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java	Fri May 06 16:21:10 2011 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.*;
 import com.sun.c1x.graph.*;
 import com.sun.c1x.ir.*;
@@ -32,8 +33,6 @@
 /**
  * The {@code FrameState} class encapsulates the frame state (i.e. local variables and
  * operand stack) at a particular point in the abstract interpretation.
- *
- * @author Ben L. Titzer
  */
 public abstract class FrameState {
 
@@ -297,8 +296,9 @@
      * Inserts a phi statement into the stack at the specified stack index.
      * @param block the block begin for which we are creating the phi
      * @param i the index into the stack for which to create a phi
+     * @param graph
      */
-    public void setupPhiForStack(BlockBegin block, int i) {
+    public void setupPhiForStack(BlockBegin block, int i, Graph graph) {
         Value p = stackAt(i);
         if (p != null) {
             if (p instanceof Phi) {
@@ -307,7 +307,7 @@
                     return;
                 }
             }
-            values[maxLocals + i] = new Phi(p.kind, block, -i - 1);
+            values[maxLocals + i] = new Phi(p.kind, block, -i - 1, graph);
         }
     }
 
@@ -315,8 +315,9 @@
      * Inserts a phi statement for the local at the specified index.
      * @param block the block begin for which we are creating the phi
      * @param i the index of the local variable for which to create the phi
+     * @param graph
      */
-    public void setupPhiForLocal(BlockBegin block, int i) {
+    public void setupPhiForLocal(BlockBegin block, int i, Graph graph) {
         Value p = values[i];
         if (p instanceof Phi) {
             Phi phi = (Phi) p;
@@ -324,7 +325,7 @@
                 return;
             }
         }
-        storeLocal(i, new Phi(p.kind, block, i));
+        storeLocal(i, new Phi(p.kind, block, i, graph));
     }
 
     /**
@@ -384,7 +385,7 @@
         }
     }
 
-    public void merge(BlockBegin block, FrameState other) {
+    public void merge(BlockBegin block, FrameState other, Graph graph) {
         checkSize(other);
         for (int i = 0; i < valuesSize(); i++) {
             Value x = values[i];
@@ -403,10 +404,10 @@
                     }
                     if (i < maxLocals) {
                         // this a local
-                        setupPhiForLocal(block, i);
+                        setupPhiForLocal(block, i, graph);
                     } else {
                         // this is a stack slot
-                        setupPhiForStack(block, i - maxLocals);
+                        setupPhiForStack(block, i - maxLocals, graph);
                     }
                 }
             }
--- a/graal/GraalGraph/src/com/oracle/graal/graph/vis/GraphvizPrinter.java	Fri May 06 16:20:56 2011 +0200
+++ b/graal/GraalGraph/src/com/oracle/graal/graph/vis/GraphvizPrinter.java	Fri May 06 16:21:10 2011 +0200
@@ -117,7 +117,7 @@
         out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\" PORT=\"predecessors\" BGCOLOR=\"rosybrown1\"></TD></TR></TABLE>");
         out.println("    </TD><TD COLSPAN=\"2\" CELLPADDING=\"0\" ALIGN=\"RIGHT\"><TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR>");
 
-        if (ninputs == 1 && nsuccessors == 1) {
+        if ((ninputs == 1 && nsuccessors == 1) || (ninputs == 0 && nsuccessors == 0)) {
             out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\"></TD>");
         }
 
@@ -129,6 +129,9 @@
             out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\" PORT=\"in" + i + "\" BGCOLOR=\"lightgrey\"></TD>");
         }
 
+        label = label.replace("&", "&amp;");
+        label = label.replace("<", "&lt;");
+        label = label.replace(">", "&gt;");
         out.println("    </TR></TABLE></TD></TR><TR><TD BORDER=\"1\" COLSPAN=\"3\" BGCOLOR=\"" + NODE_BGCOLOR_STRING + "\">" + label + "</TD></TR>");
         out.println("    <TR><TD COLSPAN=\"2\" CELLPADDING=\"0\" ALIGN=\"RIGHT\"><TABLE BORDER=\"0\" CELLSPACING=\"2\" CELLPADDING=\"0\"><TR>");
 
@@ -140,7 +143,7 @@
             out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\"></TD>");
         }
 
-        if (ninputs == 1 && nsuccessors == 1) {
+        if ((ninputs == 1 && nsuccessors == 1) || (ninputs == 0 && nsuccessors == 0)) {
             out.println("    <TD WIDTH=\"15\" HEIGHT=\"5\"></TD>");
         }
 
--- a/rundacapo.sh	Fri May 06 16:20:56 2011 +0200
+++ b/rundacapo.sh	Fri May 06 16:21:10 2011 +0200
@@ -12,7 +12,7 @@
   exit 1;
 fi
 if [ -z "${DACAPO}" ]; then
-  echo "DACAPO is not defined. It must point to a SciMark benchmark directory."
+  echo "DACAPO is not defined. It must point to a Dacapo benchmark directory."
   exit 1;
 fi
 ${JDK7}/bin/java -client -graal -XX:-C1XBailoutIsFatal -C1X:+QuietBailout -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar Harness $*
--- a/runscimark.sh	Fri May 06 16:20:56 2011 +0200
+++ b/runscimark.sh	Fri May 06 16:21:10 2011 +0200
@@ -12,7 +12,7 @@
   exit 1;
 fi
 if [ -z "${SCIMARK}" ]; then
-  echo "SCIMARK is not defined. It must point to a SciMark benchmark directory."
+  echo "SCIMARK is not defined. It must point to a SciMark benchmark jar."
   exit 1;
 fi
 COUNT=$1