changeset 2616:3558ca7088c0

FrameState and Graphviz changes: * removed popx, pushx methods from GraphBuilder * FrameState subclass of Value * added String shortName() to Node * added GraphvizPrinter option to use short names * small hack in GraphvizPrinter: omit FrameState->Local connections * added GraalGraphviz to implicit classpatch (read from GRAAL env var)
author Lukas Stadler <lukas.stadler@jku.at>
date Mon, 09 May 2011 17:00:25 +0200
parents 5768534fd4e5
children 1be9b1ddd5c1
files graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java graal/GraalCompiler/src/com/sun/c1x/graph/IR.java graal/GraalCompiler/src/com/sun/c1x/ir/ArithmeticOp.java graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java graal/GraalCompiler/src/com/sun/c1x/ir/Constant.java graal/GraalCompiler/src/com/sun/c1x/ir/If.java graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java graal/GraalCompiler/src/com/sun/c1x/ir/MonitorEnter.java graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java graal/GraalCompiler/src/com/sun/c1x/opt/InstructionSubstituter.java graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java graal/GraalGraph/src/com/oracle/graal/graph/Node.java graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java graal/GraalGraphviz/test/com/oracle/graal/graph/vis/GraphvizTest.java src/share/vm/runtime/arguments.cpp
diffstat 23 files changed, 435 insertions(+), 376 deletions(-) [+]
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java	Mon May 09 17:00:25 2011 +0200
@@ -25,6 +25,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.graph.*;
 import com.sun.c1x.alloc.*;
 import com.sun.c1x.asm.*;
 import com.sun.c1x.gen.*;
@@ -56,6 +57,8 @@
     public final CiAssumptions assumptions = new CiAssumptions();
     public final FrameState placeholderState;
 
+    public final Graph graph = new Graph();
+
     private boolean hasExceptionHandlers;
     private final C1XCompilation parent;
 
@@ -94,7 +97,7 @@
         this.method = method;
         this.stats = stats == null ? new CiStatistics() : stats;
         this.registerConfig = method == null ? compiler.globalStubRegisterConfig : runtime.getRegisterConfig(method);
-        this.placeholderState = method != null && method.minimalDebugInfo() ? new FrameState(0, 0, 0, 0) : null;
+        this.placeholderState = method != null && method.minimalDebugInfo() ? new FrameState(0, 0, 0, 0, graph) : null;
 
         if (compiler.isObserved()) {
             compiler.fireCompilationStarted(new CompilationEvent(this));
@@ -166,7 +169,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(), hir.graph());
+        BlockMap map = new BlockMap(method, hir.numberOfBlocks(), graph);
         if (!map.build(C1XOptions.PhiLoopStores)) {
             throw new CiBailout("build of BlockMap failed for " + method);
         } else {
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompiler.java	Mon May 09 17:00:25 2011 +0200
@@ -155,7 +155,7 @@
                             ByteArrayOutputStream out = new ByteArrayOutputStream();
                             GraphvizPrinter printer = new GraphvizPrinter(out);
                             printer.begin(name);
-                            printer.print(graph);
+                            printer.print(graph, true);
                             printer.end();
 
                             try {
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Mon May 09 17:00:25 2011 +0200
@@ -182,8 +182,7 @@
             flags |= Flag.HasHandler.mask;
         }
 
-        FrameState initialState = frameState.create(-1);
-        startBlock.mergeOrClone(initialState, rootMethod);
+        startBlock.mergeOrClone(frameState, rootMethod);
         BlockBegin syncHandler = null;
 
         // 3. setup internal state for appending instructions
@@ -193,7 +192,7 @@
 
         if (isSynchronized(rootMethod.accessFlags())) {
             // 4A.1 add a monitor enter to the start block
-            rootMethodSynchronizedObject = synchronizedObject(initialState, compilation.method);
+            rootMethodSynchronizedObject = synchronizedObject(frameState, compilation.method);
             genMonitorEnter(rootMethodSynchronizedObject, Instruction.SYNCHRONIZATION_ENTRY_BCI);
             // 4A.2 finish the start block
             finishStartBlock(startBlock, stdEntry);
@@ -251,84 +250,12 @@
         return stream.nextBCI();
     }
 
-    private void ipush(Value x) {
-        frameState.ipush(x);
-    }
-
-    private void lpush(Value x) {
-        frameState.lpush(x);
-    }
-
-    private void fpush(Value x) {
-        frameState.fpush(x);
-    }
-
-    private void dpush(Value x) {
-        frameState.dpush(x);
-    }
-
-    private void apush(Value x) {
-        frameState.apush(x);
-    }
-
-    private void wpush(Value x) {
-        frameState.wpush(x);
-    }
-
-    private void push(CiKind kind, Value x) {
-        frameState.push(kind, x);
-    }
-
-    private void pushReturn(CiKind kind, Value x) {
-        if (kind != CiKind.Void) {
-            frameState.push(kind.stackKind(), x);
-        }
-    }
-
-    private Value ipop() {
-        return frameState.ipop();
-    }
-
-    private Value lpop() {
-        return frameState.lpop();
-    }
-
-    private Value fpop() {
-        return frameState.fpop();
-    }
-
-    private Value dpop() {
-        return frameState.dpop();
-    }
-
-    private Value apop() {
-        return frameState.apop();
-    }
-
-    private Value wpop() {
-        return frameState.wpop();
-    }
-
-    private Value pop(CiKind kind) {
-        return frameState.pop(kind);
-    }
-
-    private CiKind peekKind() {
-        Value top = frameState.stackAt(frameState.stackSize() - 1);
-        if (top == null) {
-            top = frameState.stackAt(frameState.stackSize() - 2);
-            assert top != null;
-            assert top.kind.isDoubleWord();
-        }
-        return top.kind;
-    }
-
     private void loadLocal(int index, CiKind kind) {
-        push(kind, frameState.loadLocal(index));
+        frameState.push(kind, frameState.loadLocal(index));
     }
 
     private void storeLocal(CiKind kind, int index) {
-        frameState.storeLocal(index, pop(kind));
+        frameState.storeLocal(index, frameState.pop(kind));
     }
 
     List<ExceptionHandler> handleException(Instruction x, int bci) {
@@ -380,7 +307,7 @@
         assert entryState == null || curState.locksSize() == entryState.locksSize() : "locks do not match : cur:" + curState.locksSize() + " entry:" + entryState.locksSize();
 
         // exception handler starts with an empty expression stack
-        curState = curState.copyWithEmptyStack();
+        curState = curState.duplicateWithEmptyStack();
 
         entry.mergeOrClone(curState, method());
 
@@ -422,13 +349,13 @@
             // 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, graph)));
+                frameState.push(CiKind.Object, append(new ResolveClass(riType, RiType.Representation.JavaClass, null, graph)));
             } else {
-                push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph)));
+                frameState.push(CiKind.Object, append(new Constant(riType.getEncoding(Representation.JavaClass), graph)));
             }
         } else if (con instanceof CiConstant) {
             CiConstant constant = (CiConstant) con;
-            push(constant.kind.stackKind(), appendConstant(constant));
+            frameState.push(constant.kind.stackKind(), appendConstant(constant));
         } else {
             throw new Error("lookupConstant returned an object of incorrect type");
         }
@@ -436,21 +363,21 @@
 
     void genLoadIndexed(CiKind kind) {
         FrameState stateBefore = frameState.create(bci());
-        Value index = ipop();
-        Value array = apop();
+        Value index = frameState.ipop();
+        Value array = frameState.apop();
         Value length = null;
         if (cseArrayLength(array)) {
             length = append(new ArrayLength(array, stateBefore, graph));
         }
         Value v = append(new LoadIndexed(array, index, length, kind, stateBefore, graph));
-        push(kind.stackKind(), v);
+        frameState.push(kind.stackKind(), v);
     }
 
     void genStoreIndexed(CiKind kind) {
         FrameState stateBefore = frameState.create(bci());
-        Value value = pop(kind.stackKind());
-        Value index = ipop();
-        Value array = apop();
+        Value value = frameState.pop(kind.stackKind());
+        Value index = frameState.ipop();
+        Value array = frameState.apop();
         Value length = null;
         if (cseArrayLength(array)) {
             length = append(new ArrayLength(array, stateBefore, graph));
@@ -552,41 +479,41 @@
     }
 
     void genArithmeticOp(CiKind result, int opcode, CiKind x, CiKind y, FrameState state) {
-        Value yValue = pop(y);
-        Value xValue = pop(x);
+        Value yValue = frameState.pop(y);
+        Value xValue = frameState.pop(x);
         Value result1 = append(new ArithmeticOp(opcode, result, xValue, yValue, isStrict(method().accessFlags()), state, graph));
-        push(result, result1);
+        frameState.push(result, result1);
     }
 
     void genNegateOp(CiKind kind) {
-        push(kind, append(new NegateOp(pop(kind), graph)));
+        frameState.push(kind, append(new NegateOp(frameState.pop(kind), graph)));
     }
 
     void genShiftOp(CiKind kind, int opcode) {
-        Value s = ipop();
-        Value x = pop(kind);
+        Value s = frameState.ipop();
+        Value x = frameState.pop(kind);
         // note that strength reduction of e << K >>> K is correctly handled in canonicalizer now
-        push(kind, append(new ShiftOp(opcode, x, s, graph)));
+        frameState.push(kind, append(new ShiftOp(opcode, x, s, graph)));
     }
 
     void genLogicOp(CiKind kind, int opcode) {
-        Value y = pop(kind);
-        Value x = pop(kind);
-        push(kind, append(new LogicOp(opcode, x, y, graph)));
+        Value y = frameState.pop(kind);
+        Value x = frameState.pop(kind);
+        frameState.push(kind, append(new LogicOp(opcode, x, y, graph)));
     }
 
     void genCompareOp(CiKind kind, int opcode, CiKind resultKind) {
-        Value y = pop(kind);
-        Value x = pop(kind);
+        Value y = frameState.pop(kind);
+        Value x = frameState.pop(kind);
         Value value = append(new CompareOp(opcode, resultKind, x, y, graph));
         if (!resultKind.isVoid()) {
-            ipush(value);
+            frameState.ipush(value);
         }
     }
 
     void genConvert(int opcode, CiKind from, CiKind to) {
         CiKind tt = to.stackKind();
-        push(tt, append(new Convert(opcode, pop(from.stackKind()), tt, graph)));
+        frameState.push(tt, append(new Convert(opcode, frameState.pop(from.stackKind()), tt, graph)));
     }
 
     void genIncrement() {
@@ -613,27 +540,27 @@
     void genIfZero(Condition cond) {
         Value y = appendConstant(CiConstant.INT_0);
         FrameState stateBefore = frameState.create(bci());
-        Value x = ipop();
+        Value x = frameState.ipop();
         ifNode(x, cond, y, stateBefore);
     }
 
     void genIfNull(Condition cond) {
         FrameState stateBefore = frameState.create(bci());
         Value y = appendConstant(CiConstant.NULL_OBJECT);
-        Value x = apop();
+        Value x = frameState.apop();
         ifNode(x, cond, y, stateBefore);
     }
 
     void genIfSame(CiKind kind, Condition cond) {
         FrameState stateBefore = frameState.create(bci());
-        Value y = pop(kind);
-        Value x = pop(kind);
+        Value y = frameState.pop(kind);
+        Value x = frameState.pop(kind);
         ifNode(x, cond, y, stateBefore);
     }
 
     void genThrow(int bci) {
         FrameState stateBefore = frameState.create(bci());
-        Throw t = new Throw(apop(), stateBefore, !noSafepoints(), graph);
+        Throw t = new Throw(frameState.apop(), stateBefore, !noSafepoints(), graph);
         appendWithoutOptimization(t, bci);
     }
 
@@ -642,8 +569,8 @@
         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, graph);
-        apush(append(c));
+        CheckCast c = new CheckCast(type, typeInstruction, frameState.apop(), null, graph);
+        frameState.apush(append(c));
         checkForDirectCompare(c);
     }
 
@@ -652,8 +579,8 @@
         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, graph);
-        ipush(append(i));
+        InstanceOf i = new InstanceOf(type, typeInstruction, frameState.apop(), null, graph);
+        frameState.ipush(append(i));
         checkForDirectCompare(i);
     }
 
@@ -671,21 +598,21 @@
         if (memoryMap != null) {
             memoryMap.newInstance(n);
         }
-        apush(append(n));
+        frameState.apush(append(n));
     }
 
     void genNewTypeArray(int typeCode) {
         FrameState stateBefore = frameState.create(bci());
         CiKind kind = CiKind.fromArrayTypeCode(typeCode);
         RiType elementType = compilation.runtime.asRiType(kind);
-        apush(append(new NewTypeArray(ipop(), elementType, stateBefore, graph)));
+        frameState.apush(append(new NewTypeArray(frameState.ipop(), elementType, stateBefore, graph)));
     }
 
     void genNewObjectArray(int cpi) {
         RiType type = constantPool().lookupType(cpi, ANEWARRAY);
         FrameState stateBefore = frameState.create(bci());
-        NewArray n = new NewObjectArray(type, ipop(), stateBefore, graph);
-        apush(append(n));
+        NewArray n = new NewObjectArray(type, frameState.ipop(), stateBefore, graph);
+        frameState.apush(append(n));
     }
 
     void genNewMultiArray(int cpi) {
@@ -694,24 +621,24 @@
         int rank = stream().readUByte(bci() + 3);
         Value[] dims = new Value[rank];
         for (int i = rank - 1; i >= 0; i--) {
-            dims[i] = ipop();
+            dims[i] = frameState.ipop();
         }
         NewArray n = new NewMultiArray(type, dims, stateBefore, cpi, constantPool(), graph);
-        apush(append(n));
+        frameState.apush(append(n));
     }
 
     void genGetField(int cpi, RiField field) {
         // Must copy the state here, because the field holder must still be on the stack.
         FrameState stateBefore = frameState.create(bci());
-        LoadField load = new LoadField(apop(), field, stateBefore, graph);
+        LoadField load = new LoadField(frameState.apop(), field, stateBefore, graph);
         appendOptimizedLoadField(field.kind(), load);
     }
 
     void genPutField(int cpi, RiField field) {
         // Must copy the state here, because the field holder must still be on the stack.
         FrameState stateBefore = frameState.create(bci());
-        Value value = pop(field.kind().stackKind());
-        appendOptimizedStoreField(new StoreField(apop(), field, value, stateBefore, graph));
+        Value value = frameState.pop(field.kind().stackKind());
+        appendOptimizedStoreField(new StoreField(frameState.apop(), field, value, stateBefore, graph));
     }
 
     void genGetStatic(int cpi, RiField field) {
@@ -722,7 +649,7 @@
             constantValue = field.constantValue(null);
         }
         if (constantValue != null) {
-            push(constantValue.kind.stackKind(), appendConstant(constantValue));
+            frameState.push(constantValue.kind.stackKind(), appendConstant(constantValue));
         } else {
             Value container = genResolveClass(RiType.Representation.StaticFields, holder, field.isResolved(), cpi);
             LoadField load = new LoadField(container, field, null, graph);
@@ -733,7 +660,7 @@
     void genPutStatic(int cpi, RiField field) {
         RiType holder = field.holder();
         Value container = genResolveClass(RiType.Representation.StaticFields, holder, field.isResolved(), cpi);
-        Value value = pop(field.kind().stackKind());
+        Value value = frameState.pop(field.kind().stackKind());
         StoreField store = new StoreField(container, field, value, null, graph);
         appendOptimizedStoreField(store);
     }
@@ -764,7 +691,7 @@
             Value replacement = memoryMap.load(load);
             if (replacement != load) {
                 // the memory buffer found a replacement for this load (no need to append)
-                push(kind.stackKind(), replacement);
+                frameState.push(kind.stackKind(), replacement);
                 return;
             }
         }
@@ -774,7 +701,7 @@
             // local optimization happened, replace its value in the memory map
             memoryMap.setResult(load, optimized);
         }
-        push(kind.stackKind(), optimized);
+        frameState.push(kind.stackKind(), optimized);
     }
 
     void genInvokeStatic(RiMethod target, int cpi, RiConstantPool constantPool) {
@@ -904,7 +831,7 @@
     private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool, FrameState stateBefore) {
         CiKind resultType = returnKind(target);
         Value result = append(new Invoke(opcode, resultType.stackKind(), args, target, target.signature().returnType(compilation.method.holder()), stateBefore, graph));
-        pushReturn(resultType, result);
+        frameState.pushReturn(resultType, result);
     }
 
     private RiType getExactType(RiType staticType, Value receiver) {
@@ -1092,7 +1019,7 @@
         list.add(blockAt(bci + offset));
         boolean isSafepoint = isBackwards && !noSafepoints();
         FrameState stateBefore = isSafepoint ? frameState.create(bci()) : null;
-        append(new TableSwitch(ipop(), list, ts.lowKey(), stateBefore, isSafepoint, graph));
+        append(new TableSwitch(frameState.ipop(), list, ts.lowKey(), stateBefore, isSafepoint, graph));
     }
 
     void genLookupswitch() {
@@ -1114,7 +1041,7 @@
         list.add(blockAt(bci + offset));
         boolean isSafepoint = isBackwards && !noSafepoints();
         FrameState stateBefore = isSafepoint ? frameState.create(bci()) : null;
-        append(new LookupSwitch(ipop(), list, keys, stateBefore, isSafepoint, graph));
+        append(new LookupSwitch(frameState.ipop(), list, keys, stateBefore, isSafepoint, graph));
     }
 
     /**
@@ -1217,7 +1144,7 @@
         return result;
     }
 
-    private Value synchronizedObject(FrameState curState2, RiMethod target) {
+    private Value synchronizedObject(FrameStateAccess curState2, RiMethod target) {
         if (isStatic(target.accessFlags())) {
             Constant classConstant = new Constant(target.holder().getEncoding(Representation.JavaClass), graph);
             return appendWithoutOptimization(classConstant, Instruction.SYNCHRONIZATION_ENTRY_BCI);
@@ -1252,7 +1179,7 @@
         // exit the monitor
         genMonitorExit(lock, Instruction.SYNCHRONIZATION_ENTRY_BCI);
 
-        apush(exception);
+        frameState.apush(exception);
         genThrow(bci);
         BlockEnd end = (BlockEnd) lastInstr;
         curBlock.setEnd(end);
@@ -1260,6 +1187,7 @@
 
         curBlock = origBlock;
         frameState.initializeFrom(origState);
+        origState.delete();
         lastInstr = origLast;
     }
 
@@ -1314,7 +1242,7 @@
             // push an exception object onto the stack if we are parsing an exception handler
             if (pushException) {
                 FrameState stateBefore = frameState.create(bci());
-                apush(append(new ExceptionObject(stateBefore, graph)));
+                frameState.apush(append(new ExceptionObject(stateBefore, graph)));
                 pushException = false;
             }
 
@@ -1382,23 +1310,23 @@
         // Checkstyle: stop
         switch (opcode) {
             case NOP            : /* nothing to do */ break;
-            case ACONST_NULL    : apush(appendConstant(CiConstant.NULL_OBJECT)); break;
-            case ICONST_M1      : ipush(appendConstant(CiConstant.INT_MINUS_1)); break;
-            case ICONST_0       : ipush(appendConstant(CiConstant.INT_0)); break;
-            case ICONST_1       : ipush(appendConstant(CiConstant.INT_1)); break;
-            case ICONST_2       : ipush(appendConstant(CiConstant.INT_2)); break;
-            case ICONST_3       : ipush(appendConstant(CiConstant.INT_3)); break;
-            case ICONST_4       : ipush(appendConstant(CiConstant.INT_4)); break;
-            case ICONST_5       : ipush(appendConstant(CiConstant.INT_5)); break;
-            case LCONST_0       : lpush(appendConstant(CiConstant.LONG_0)); break;
-            case LCONST_1       : lpush(appendConstant(CiConstant.LONG_1)); break;
-            case FCONST_0       : fpush(appendConstant(CiConstant.FLOAT_0)); break;
-            case FCONST_1       : fpush(appendConstant(CiConstant.FLOAT_1)); break;
-            case FCONST_2       : fpush(appendConstant(CiConstant.FLOAT_2)); break;
-            case DCONST_0       : dpush(appendConstant(CiConstant.DOUBLE_0)); break;
-            case DCONST_1       : dpush(appendConstant(CiConstant.DOUBLE_1)); break;
-            case BIPUSH         : ipush(appendConstant(CiConstant.forInt(s.readByte()))); break;
-            case SIPUSH         : ipush(appendConstant(CiConstant.forInt(s.readShort()))); break;
+            case ACONST_NULL    : frameState.apush(appendConstant(CiConstant.NULL_OBJECT)); break;
+            case ICONST_M1      : frameState.ipush(appendConstant(CiConstant.INT_MINUS_1)); break;
+            case ICONST_0       : frameState.ipush(appendConstant(CiConstant.INT_0)); break;
+            case ICONST_1       : frameState.ipush(appendConstant(CiConstant.INT_1)); break;
+            case ICONST_2       : frameState.ipush(appendConstant(CiConstant.INT_2)); break;
+            case ICONST_3       : frameState.ipush(appendConstant(CiConstant.INT_3)); break;
+            case ICONST_4       : frameState.ipush(appendConstant(CiConstant.INT_4)); break;
+            case ICONST_5       : frameState.ipush(appendConstant(CiConstant.INT_5)); break;
+            case LCONST_0       : frameState.lpush(appendConstant(CiConstant.LONG_0)); break;
+            case LCONST_1       : frameState.lpush(appendConstant(CiConstant.LONG_1)); break;
+            case FCONST_0       : frameState.fpush(appendConstant(CiConstant.FLOAT_0)); break;
+            case FCONST_1       : frameState.fpush(appendConstant(CiConstant.FLOAT_1)); break;
+            case FCONST_2       : frameState.fpush(appendConstant(CiConstant.FLOAT_2)); break;
+            case DCONST_0       : frameState.dpush(appendConstant(CiConstant.DOUBLE_0)); break;
+            case DCONST_1       : frameState.dpush(appendConstant(CiConstant.DOUBLE_1)); break;
+            case BIPUSH         : frameState.ipush(appendConstant(CiConstant.forInt(s.readByte()))); break;
+            case SIPUSH         : frameState.ipush(appendConstant(CiConstant.forInt(s.readShort()))); break;
             case LDC            : // fall through
             case LDC_W          : // fall through
             case LDC2_W         : genLoadConstant(s.readCPI()); break;
@@ -1546,18 +1474,18 @@
             case IF_ICMPGE      : genIfSame(CiKind.Int, Condition.GE); break;
             case IF_ICMPGT      : genIfSame(CiKind.Int, Condition.GT); break;
             case IF_ICMPLE      : genIfSame(CiKind.Int, Condition.LE); break;
-            case IF_ACMPEQ      : genIfSame(peekKind(), Condition.EQ); break;
-            case IF_ACMPNE      : genIfSame(peekKind(), Condition.NE); break;
+            case IF_ACMPEQ      : genIfSame(frameState.peekKind(), Condition.EQ); break;
+            case IF_ACMPNE      : genIfSame(frameState.peekKind(), Condition.NE); break;
             case GOTO           : genGoto(s.currentBCI(), s.readBranchDest()); break;
             case JSR            : genJsr(s.readBranchDest()); break;
             case RET            : genRet(s.readLocalIndex()); break;
             case TABLESWITCH    : genTableswitch(); break;
             case LOOKUPSWITCH   : genLookupswitch(); break;
-            case IRETURN        : genReturn(ipop()); break;
-            case LRETURN        : genReturn(lpop()); break;
-            case FRETURN        : genReturn(fpop()); break;
-            case DRETURN        : genReturn(dpop()); break;
-            case ARETURN        : genReturn(apop()); break;
+            case IRETURN        : genReturn(frameState.ipop()); break;
+            case LRETURN        : genReturn(frameState.lpop()); break;
+            case FRETURN        : genReturn(frameState.fpop()); break;
+            case DRETURN        : genReturn(frameState.dpop()); break;
+            case ARETURN        : genReturn(frameState.apop()); break;
             case RETURN         : genReturn(null  ); break;
             case GETSTATIC      : cpi = s.readCPI(); genGetStatic(cpi, constantPool().lookupField(cpi, opcode)); break;
             case PUTSTATIC      : cpi = s.readCPI(); genPutStatic(cpi, constantPool().lookupField(cpi, opcode)); break;
@@ -1574,8 +1502,8 @@
             case ATHROW         : genThrow(s.currentBCI()); break;
             case CHECKCAST      : genCheckCast(); break;
             case INSTANCEOF     : genInstanceOf(); break;
-            case MONITORENTER   : genMonitorEnter(apop(), s.currentBCI()); break;
-            case MONITOREXIT    : genMonitorExit(apop(), s.currentBCI()); break;
+            case MONITORENTER   : genMonitorEnter(frameState.apop(), s.currentBCI()); break;
+            case MONITOREXIT    : genMonitorExit(frameState.apop(), s.currentBCI()); break;
             case MULTIANEWARRAY : genNewMultiArray(s.readCPI()); break;
             case IFNULL         : genIfNull(Condition.EQ); break;
             case IFNONNULL      : genIfNull(Condition.NE); break;
@@ -1608,7 +1536,7 @@
 
     private void genArrayLength() {
         FrameState stateBefore = frameState.create(bci());
-        ipush(append(new ArrayLength(apop(), stateBefore, graph)));
+        frameState.ipush(append(new ArrayLength(frameState.apop(), stateBefore, graph)));
     }
 
     void killMemoryMap() {
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Mon May 09 17:00:25 2011 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.graal.graph.*;
 import com.sun.c1x.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.ir.*;
@@ -62,8 +61,6 @@
      */
     private List<BlockBegin> orderedBlocks;
 
-    private final Graph graph = new Graph();
-
     /**
      * Creates a new IR instance for the specified compilation.
      * @param compilation the compilation
@@ -96,7 +93,7 @@
 
     private void buildGraph() {
         // Graph builder must set the startBlock and the osrEntryBlock
-        new GraphBuilder(compilation, this, graph).build();
+        new GraphBuilder(compilation, this, compilation.graph).build();
         assert startBlock != null;
         verifyAndPrint("After graph building");
 
@@ -176,12 +173,12 @@
         }
 
         // create new successor and mark it for special block order treatment
-        BlockBegin newSucc = new BlockBegin(bci, nextBlockNumber(), graph);
+        BlockBegin newSucc = new BlockBegin(bci, nextBlockNumber(), compilation.graph);
 
         newSucc.setCriticalEdgeSplit(true);
 
         // This goto is not a safepoint.
-        Goto e = new Goto(target, null, false, graph);
+        Goto e = new Goto(target, null, false, compilation.graph);
         newSucc.appendNext(e, bci);
         newSucc.setEnd(e);
         // setup states
@@ -276,8 +273,4 @@
     public final int maxLocks() {
         return maxLocks;
     }
-
-    public Graph graph() {
-        return graph;
-    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ArithmeticOp.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ArithmeticOp.java	Mon May 09 17:00:25 2011 +0200
@@ -33,10 +33,33 @@
  */
 public final class ArithmeticOp extends Op2 {
 
-    private static final int INPUT_COUNT = 0;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_STATE_BEFORE = 0;
+
     private static final int SUCCESSOR_COUNT = 0;
 
-    private final FrameState stateBefore;
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The state for this instruction.
+     */
+     @Override
+    public FrameState stateBefore() {
+        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_BEFORE);
+    }
+
+    private FrameState setStateBefore(FrameState n) {
+        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_BEFORE, n);
+    }
+
     private final boolean isStrictFP;
 
     /**
@@ -51,12 +74,7 @@
     public ArithmeticOp(int opcode, CiKind kind, Value x, Value y, boolean isStrictFP, FrameState stateBefore, Graph graph) {
         super(kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.isStrictFP = isStrictFP;
-        this.stateBefore = stateBefore;
-    }
-
-    @Override
-    public FrameState stateBefore() {
-        return stateBefore;
+        setStateBefore(stateBefore);
     }
 
     /**
@@ -74,7 +92,7 @@
      */
     @Override
     public boolean canTrap() {
-        return stateBefore != null;
+        return stateBefore() != null;
     }
 
     @Override
@@ -90,4 +108,9 @@
     public void print(LogStream out) {
         out.print(x()).print(' ').print(Bytecodes.operator(opcode)).print(' ').print(y());
     }
+
+    @Override
+    public String shortName() {
+        return Bytecodes.operator(opcode);
+    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java	Mon May 09 17:00:25 2011 +0200
@@ -41,9 +41,34 @@
  */
 public final class BlockBegin extends Instruction {
 
-    private static final int INPUT_COUNT = 0;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_STATE_BEFORE = 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 frame state before execution of the first instruction in this block.
+     */
+     @Override
+    public FrameState stateBefore() {
+        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_BEFORE);
+    }
+
+    public FrameState setStateBefore(FrameState n) {
+        assert stateBefore() == null;
+        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_BEFORE, n);
+    }
+
     private static final List<BlockBegin> NO_HANDLERS = Collections.emptyList();
 
     /**
@@ -76,11 +101,6 @@
     private int blockFlags;
 
     /**
-     * The frame state before execution of the first instruction in this block.
-     */
-    private FrameState stateBefore;
-
-    /**
      * A link to the last node in the block (which contains the successors).
      */
     private BlockEnd end;
@@ -183,24 +203,6 @@
     }
 
     /**
-     * Gets the state at the start of this block.
-     * @return the state at the start of this block
-     */
-    @Override
-    public FrameState stateBefore() {
-        return stateBefore;
-    }
-
-    /**
-     * Sets the initial state for this block.
-     * @param stateBefore the state for this block
-     */
-    public void setStateBefore(FrameState stateBefore) {
-        assert this.stateBefore == null;
-        this.stateBefore = stateBefore;
-    }
-
-    /**
      * Gets the exception handlers that cover one or more instructions of this basic block.
      *
      * @return the exception handlers
@@ -399,8 +401,8 @@
         v.visitBlockBegin(this);
     }
 
-    public void mergeOrClone(FrameState newState, RiMethod method) {
-        FrameState existingState = stateBefore;
+    public void mergeOrClone(FrameStateAccess newState, RiMethod method) {
+        FrameState existingState = stateBefore();
 
         if (existingState == null) {
             // this is the first state for the block
@@ -410,7 +412,7 @@
             }
 
             // copy state because it is modified
-            newState = newState.copy();
+            FrameState duplicate = newState.duplicate();
 
             if (C1XOptions.UseStackMapTableLiveness) {
                 // if a liveness map is available, use it to invalidate dead locals
@@ -419,17 +421,17 @@
                     assert bci() < livenessMap.length;
                     CiBitMap liveness = livenessMap[bci()];
                     if (liveness != null) {
-                        invalidateDeadLocals(newState, liveness);
+                        invalidateDeadLocals(duplicate, liveness);
                     }
                 }
             }
 
             // if the block is a loop header, insert all necessary phis
             if (isParserLoopHeader()) {
-                insertLoopPhis(newState);
+                insertLoopPhis(duplicate);
             }
 
-            stateBefore = newState;
+            setStateBefore(duplicate);
         } else {
             if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(newState)) {
                 // stacks or locks do not match--bytecodes would not verify
@@ -443,7 +445,7 @@
                 throw new CiBailout("jsr/ret too complicated");
             }
 
-            existingState.merge(this, newState, graph());
+            existingState.merge(this, newState);
         }
     }
 
@@ -465,13 +467,13 @@
         int stackSize = newState.stackSize();
         for (int i = 0; i < stackSize; i++) {
             // always insert phis for the stack
-            newState.setupPhiForStack(this, i, graph());
+            newState.setupPhiForStack(this, i);
         }
         int localsSize = newState.localsSize();
         for (int i = 0; i < localsSize; i++) {
             Value x = newState.localAt(i);
             if (x != null) {
-                newState.setupPhiForLocal(this, i, graph());
+                newState.setupPhiForLocal(this, i);
             }
         }
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java	Mon May 09 17:00:25 2011 +0200
@@ -34,7 +34,8 @@
  */
 public abstract class BlockEnd extends Instruction {
 
-    private static final int INPUT_COUNT = 0;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_STATE_AFTER = 0;
 
     private final int blockSuccessorCount;
 
@@ -49,6 +50,17 @@
     }
 
     /**
+     * The state for this instruction.
+     */
+     @Override
+    public FrameState stateAfter() {
+        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER);
+    }
+
+    public FrameState setStateAfter(FrameState n) {
+        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_AFTER, n);
+    }
+    /**
      * The list of instructions that produce input for this instruction.
      */
     public BlockBegin blockSuccessor(int index) {
@@ -66,7 +78,6 @@
     }
 
     BlockBegin begin;
-    FrameState stateAfter;
     boolean isSafepoint;
 
     /**
@@ -95,18 +106,6 @@
     }
 
     /**
-     * Gets the state after the end of this block.
-     */
-    @Override
-    public FrameState stateAfter() {
-        return stateAfter;
-    }
-
-    public void setStateAfter(FrameState state) {
-        stateAfter = state;
-    }
-
-    /**
      * Checks whether this instruction is a safepoint.
      * @return {@code true} if this instruction is a safepoint
      */
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Constant.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Constant.java	Mon May 09 17:00:25 2011 +0200
@@ -164,4 +164,10 @@
     public void print(LogStream out) {
         out.print(value.valueString());
     }
+
+    @Override
+    public String shortName() {
+        return value.name();
+    }
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/If.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/If.java	Mon May 09 17:00:25 2011 +0200
@@ -191,4 +191,11 @@
             out.print(" (safepoint)");
         }
     }
+
+    @Override
+    public String shortName() {
+        return "If " + condition.operator;
+    }
+
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java	Mon May 09 17:00:25 2011 +0200
@@ -239,11 +239,11 @@
         inputValuesDo(closure);
         FrameState stateBefore = stateBefore();
         if (stateBefore != null) {
-            stateBefore.valuesDo(closure);
+            stateBefore.inputValuesDo(closure);
         }
         FrameState stateAfter = stateAfter();
         if (stateAfter != null) {
-            stateAfter.valuesDo(closure);
+            stateAfter.inputValuesDo(closure);
         }
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorEnter.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorEnter.java	Mon May 09 17:00:25 2011 +0200
@@ -31,10 +31,32 @@
  */
 public final class MonitorEnter extends AccessMonitor {
 
-    private static final int INPUT_COUNT = 0;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_STATE_AFTER = 0;
+
     private static final int SUCCESSOR_COUNT = 0;
 
-    private FrameState stateAfter;
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The state for this instruction.
+     */
+     @Override
+    public FrameState stateAfter() {
+        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER);
+    }
+
+    public FrameState setStateAfter(FrameState n) {
+        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_AFTER, n);
+    }
 
     /**
      * Creates a new MonitorEnter instruction.
@@ -54,15 +76,6 @@
         v.visitMonitorEnter(this);
     }
 
-    public void setStateAfter(FrameState frameState) {
-        this.stateAfter = frameState;
-    }
-
-    @Override
-    public FrameState stateAfter() {
-        return stateAfter;
-    }
-
     @Override
     public void print(LogStream out) {
         out.print("enter monitor[").print(lockNumber).print("](").print(object()).print(')');
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java	Mon May 09 17:00:25 2011 +0200
@@ -167,4 +167,11 @@
     public void print(LogStream out) {
         out.print("phi function");
     }
+
+    @Override
+    public String shortName() {
+        return "Phi: " + index;
+    }
+
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java	Mon May 09 17:00:25 2011 +0200
@@ -32,10 +32,32 @@
  */
 public abstract class StateSplit extends Instruction {
 
-    private static final int INPUT_COUNT = 0;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_STATE_BEFORE = 0;
+
     private static final int SUCCESSOR_COUNT = 0;
 
-    private FrameState stateBefore;
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The state for this instruction.
+     */
+     @Override
+    public FrameState stateBefore() {
+        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_BEFORE);
+    }
+
+    public FrameState setStateBefore(FrameState n) {
+        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_BEFORE, n);
+    }
 
     /**
      * Creates a new state split with the specified value type.
@@ -46,30 +68,12 @@
      */
     public StateSplit(CiKind kind, FrameState stateBefore, int inputCount, int successorCount, Graph graph) {
         super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
-        this.stateBefore = stateBefore;
+        setStateBefore(stateBefore);
     }
 
     @Override
     public boolean canTrap() {
-        return stateBefore != null;
+        return stateBefore() != null;
     }
 
-    /**
-     * Records the state of this instruction before it is executed.
-     *
-     * @param stateBefore the state
-     */
-    public final void setStateBefore(FrameState stateBefore) {
-        assert this.stateBefore == null;
-        this.stateBefore = stateBefore;
-    }
-
-    /**
-     * Gets the state for this instruction.
-     * @return the state
-     */
-    @Override
-    public final FrameState stateBefore() {
-        return stateBefore;
-    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java	Mon May 09 17:00:25 2011 +0200
@@ -32,8 +32,9 @@
  */
 public final class Throw extends BlockEnd {
 
-    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_COUNT = 2;
     private static final int INPUT_EXCEPTION = 0;
+    private static final int INPUT_STATE_BEFORE = 1;
 
     private static final int SUCCESSOR_COUNT = 0;
 
@@ -58,7 +59,17 @@
         return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
     }
 
-    FrameState stateBefore;
+    /**
+     * The state before this throw would occur.
+     */
+     @Override
+    public FrameState stateBefore() {
+        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_BEFORE);
+    }
+
+    private FrameState setStateBefore(FrameState n) {
+        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_BEFORE, n);
+    }
 
     /**
      * Creates a new Throw instruction.
@@ -69,20 +80,11 @@
      */
     public Throw(Value exception, FrameState stateAfter, boolean isSafepoint, Graph graph) {
         super(CiKind.Illegal, null, isSafepoint, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        this.stateBefore = stateAfter;
+        setStateBefore(stateAfter);
         setException(exception);
     }
 
     /**
-     * Returns the state before this throw would occur.
-     * @return the state before the throw
-     */
-    @Override
-    public FrameState stateBefore() {
-        return stateBefore;
-    }
-
-    /**
      * Checks whether this instruction can trap.
      * @return {@code true} because this instruction definitely throws an exception!
      */
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java	Mon May 09 17:00:25 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.sun.c1x.ir;
 
+import com.sun.c1x.value.*;
+
 /**
  * The {@link ValueVisitor} implements one half of the visitor
  * pattern for {@linkplain Value IR values}, allowing clients to implement functionality
@@ -38,6 +40,7 @@
     public abstract void visitConstant(Constant i);
     public abstract void visitConvert(Convert i);
     public abstract void visitExceptionObject(ExceptionObject i);
+    public abstract void visitFrameState(FrameState i);
     public abstract void visitGoto(Goto i);
     public abstract void visitIf(If i);
     public abstract void visitIfOp(IfOp i);
--- a/graal/GraalCompiler/src/com/sun/c1x/opt/InstructionSubstituter.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/opt/InstructionSubstituter.java	Mon May 09 17:00:25 2011 +0200
@@ -30,8 +30,6 @@
  * This class allows instructions to be substituted within an IR graph. It allows
  * registering substitutions and iterates over the instructions of a program and replaces
  * the occurrence of each instruction with its substitution, if it has one.
- *
- * @author Ben L. Titzer
  */
 public final class InstructionSubstituter implements BlockClosure, ValueClosure {
 
@@ -46,7 +44,7 @@
         Instruction last = null;
         if (block.exceptionHandlerStates() != null) {
             for (FrameState s : block.exceptionHandlerStates()) {
-                s.valuesDo(this);
+                s.inputValuesDo(this);
             }
         }
         for (Instruction n = block; n != null; n = last.next()) {
--- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Mon May 09 17:00:25 2011 +0200
@@ -30,6 +30,7 @@
 import com.sun.c1x.ir.*;
 import com.sun.c1x.lir.*;
 import com.sun.c1x.util.*;
+import com.sun.c1x.value.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
 
@@ -568,4 +569,9 @@
     protected CiValue osrBufferPointer() {
         return Util.nonFatalUnimplemented(null);
     }
+
+    @Override
+    public void visitFrameState(FrameState i) {
+        // nothing to do for now
+    }
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java	Mon May 09 17:00:25 2011 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.graph.*;
 import com.sun.c1x.*;
+import com.sun.c1x.debug.*;
 import com.sun.c1x.ir.*;
 import com.sun.cri.ci.*;
 
@@ -35,28 +36,26 @@
  * The {@code FrameState} class encapsulates the frame state (i.e. local variables and
  * operand stack) at a particular point in the abstract interpretation.
  */
-public class FrameState {
+public class FrameState extends Value implements FrameStateAccess {
 
-    /**
-     * The operand stack and local variables.
-     * The local variables occupy the index range {@code [0 .. maxLocals)}.
-     * The operand stack occupies the index range {@code [maxLocals .. values.length)}.
-     * The top of the operand stack is at index {@code maxLocals + stackIndex}.
-     * This does not include the operand stack or local variables of parent frames.
-     *
-     * {@linkplain CiKind#isDoubleWord() Double-word} local variables and
-     * operand stack values occupy 2 slots in this array with the second slot
-     * being {@code null}.
-     */
-    protected final Value[] values;
-
-    /**
-     * The number of local variables.
-     */
     protected final int localsSize;
 
     protected final int stackSize;
 
+    protected final int locksSize;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + localsSize + stackSize + locksSize;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
     /**
      * The bytecode index to which this frame state applies. This will be {@code -1}
      * iff this state is mutable.
@@ -71,44 +70,53 @@
      * @param stackSize size of the stack
      * @param lockSize number of locks
      */
-    public FrameState(int bci, int localsSize, int stackSize, int lockSize) {
+    public FrameState(int bci, int localsSize, int stackSize, int locksSize, Graph graph) {
+        super(CiKind.Illegal, localsSize + stackSize + locksSize, SUCCESSOR_COUNT, graph);
         this.bci = bci;
-        this.values = new Value[localsSize + stackSize + lockSize];
         this.localsSize = localsSize;
         this.stackSize = stackSize;
+        this.locksSize = locksSize;
         C1XMetrics.FrameStatesCreated++;
-        C1XMetrics.FrameStateValuesCreated += this.values.length;
+        C1XMetrics.FrameStateValuesCreated += localsSize + stackSize + locksSize;
     }
 
-    FrameState(int bci, Value[] locals, Value[] stack, int stackSize, ArrayList<Value> locks) {
-        this(bci, locals.length, stackSize, locks.size());
-        System.arraycopy(locals, 0, values, 0, locals.length);
-        System.arraycopy(stack, 0, values, locals.length, stackSize);
+    FrameState(int bci, Value[] locals, Value[] stack, int stackSize, ArrayList<Value> locks, Graph graph) {
+        this(bci, locals.length, stackSize, locks.size(), graph);
+        for (int i = 0; i < locals.length; i++) {
+            inputs().set(i, locals[i]);
+        }
+        for (int i = 0; i < stackSize; i++) {
+            inputs().set(i + localsSize, stack[i]);
+        }
         for (int i = 0; i < locks.size(); i++) {
-            values[locals.length + stackSize + i] = locks.get(i);
+            inputs().set(locals.length + stackSize + i, locks.get(i));
         }
     }
 
     /**
-     * Gets a immutable copy ({@link FrameState}) of this frame state.
+     * Gets a copy of this frame state.
      */
-    public FrameState copy() {
-        FrameState other = new FrameState(bci, localsSize, stackSize, locksSize());
-        System.arraycopy(values, 0, other.values, 0, values.length);
+    public FrameState duplicate() {
+        FrameState other = copy();
+        other.inputs().setAll(inputs());
         return other;
     }
 
     /**
-     * Gets an immutable copy of this frame state but without the stack.
+     * Gets a copy of this frame state without the stack.
      */
-    public FrameState copyWithEmptyStack() {
-        FrameState other = new FrameState(bci, localsSize, 0, locksSize());
-        System.arraycopy(values, 0, other.values, 0, localsSize);
-        System.arraycopy(values, localsSize + stackSize, other.values, localsSize, locksSize());
+    public FrameState duplicateWithEmptyStack() {
+        FrameState other = new FrameState(bci, localsSize, 0, locksSize(), graph());
+        for (int i = 0; i < localsSize; i++) {
+            other.inputs().set(i, localAt(i));
+        }
+        for (int i = 0; i < locksSize; i++) {
+            other.inputs().set(localsSize + i, lockAt(i));
+        }
         return other;
     }
 
-    public boolean isCompatibleWith(FrameState other) {
+    public boolean isCompatibleWith(FrameStateAccess other) {
         if (stackSize() != other.stackSize() || localsSize() != other.localsSize() || locksSize() != other.locksSize()) {
             return false;
         }
@@ -128,9 +136,7 @@
     }
 
     /**
-     * Returns the size of the local variables.
-     *
-     * @return the size of the local variables
+     * Gets the size of the local variables.
      */
     public int localsSize() {
         return localsSize;
@@ -147,7 +153,7 @@
      * Gets number of locks held by this frame state.
      */
     public int locksSize() {
-        return values.length - localsSize - stackSize;
+        return locksSize;
     }
 
     /**
@@ -160,7 +166,7 @@
         // note that for double word locals, the high slot should already be null
         // unless the local is actually dead and the high slot is being reused;
         // in either case, it is not necessary to null the high slot
-        values[i] = null;
+        inputs().set(i, null);
     }
 
     /**
@@ -173,16 +179,16 @@
     public void storeLocal(int i, Value x) {
         assert i < localsSize : "local variable index out of range: " + i;
         invalidateLocal(i);
-        values[i] = x;
+        inputs().set(i, x);
         if (isDoubleWord(x)) {
             // (tw) if this was a double word then kill i+1
-            values[i + 1] = null;
+            inputs().set(i + 1, null);
         }
         if (i > 0) {
             // if there was a double word at i - 1, then kill it
-            Value p = values[i - 1];
+            Value p = localAt(i - 1);
             if (isDoubleWord(p)) {
-                values[i - 1] = null;
+                inputs().set(i - 1, null);
             }
         }
     }
@@ -195,7 +201,7 @@
      */
     public final Value localAt(int i) {
         assert i < localsSize : "local variable index out of range: " + i;
-        return values[i];
+        return (Value) inputs().get(i);
     }
 
     /**
@@ -206,7 +212,7 @@
      */
     public final Value stackAt(int i) {
         assert i >= 0 && i < (localsSize + stackSize);
-        return values[localsSize + i];
+        return (Value) inputs().get(localsSize + i);
     }
 
     /**
@@ -216,16 +222,15 @@
      */
     public final Value lockAt(int i) {
         assert i >= 0;
-        return values[localsSize + stackSize + i];
+        return (Value) inputs().get(localsSize + stackSize + i);
     }
 
     /**
      * 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, Graph graph) {
+    public void setupPhiForStack(BlockBegin block, int i) {
         Value p = stackAt(i);
         if (p != null) {
             if (p instanceof Phi) {
@@ -234,7 +239,7 @@
                     return;
                 }
             }
-            values[localsSize + i] = new Phi(p.kind, block, -i - 1, graph);
+            inputs().set(localsSize + i, new Phi(p.kind, block, -i - 1, graph()));
         }
     }
 
@@ -242,17 +247,16 @@
      * 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, Graph graph) {
-        Value p = values[i];
+    public void setupPhiForLocal(BlockBegin block, int i) {
+        Value p = localAt(i);
         if (p instanceof Phi) {
             Phi phi = (Phi) p;
             if (phi.block() == block && phi.isLocal() && phi.localIndex() == i) {
                 return;
             }
         }
-        storeLocal(i, new Phi(p.kind, block, i, graph));
+        storeLocal(i, new Phi(p.kind, block, i, graph()));
     }
 
     /**
@@ -267,7 +271,7 @@
      */
     public final Value valueAt(int i) {
         assert i < (localsSize + stackSize);
-        return values[i];
+        return (Value) inputs().get(i);
     }
 
     /**
@@ -284,10 +288,9 @@
 
     public void checkPhis(BlockBegin block, FrameState other) {
         checkSize(other);
-        final int max = valuesSize();
-        for (int i = 0; i < max; i++) {
-            Value x = values[i];
-            Value y = other.values[i];
+        for (int i = 0; i < valuesSize(); i++) {
+            Value x = valueAt(i);
+            Value y = other.valueAt(i);
             if (x != null && x != y) {
                 if (x instanceof Phi) {
                     Phi phi = (Phi) x;
@@ -305,20 +308,20 @@
         }
     }
 
-    private void checkSize(FrameState other) {
+    private void checkSize(FrameStateAccess other) {
         if (other.stackSize() != stackSize()) {
             throw new CiBailout("stack sizes do not match");
-        } else if (other.localsSize != localsSize) {
+        } else if (other.localsSize() != localsSize) {
             throw new CiBailout("local sizes do not match");
         }
     }
 
-    public void merge(BlockBegin block, FrameState other, Graph graph) {
+    public void merge(BlockBegin block, FrameStateAccess other) {
         checkSize(other);
         for (int i = 0; i < valuesSize(); i++) {
-            Value x = values[i];
+            Value x = valueAt(i);
             if (x != null) {
-                Value y = other.values[i];
+                Value y = other.valueAt(i);
                 if (x != y) {
                     if (typeMismatch(x, y)) {
                         if (x instanceof Phi) {
@@ -327,15 +330,15 @@
                                 phi.makeDead();
                             }
                         }
-                        values[i] = null;
+                        inputs().set(i, null);
                         continue;
                     }
                     if (i < localsSize) {
                         // this a local
-                        setupPhiForLocal(block, i, graph);
+                        setupPhiForLocal(block, i);
                     } else {
                         // this is a stack slot
-                        setupPhiForStack(block, i - localsSize, graph);
+                        setupPhiForStack(block, i - localsSize);
                     }
                 }
             }
@@ -358,9 +361,8 @@
      * @param proc the call back invoked for each live phi traversed
      */
     public final boolean forEachLivePhi(BlockBegin block, PhiProcedure proc) {
-        int max = this.valuesSize();
-        for (int i = 0; i < max; i++) {
-            Value instr = values[i];
+        for (int i = 0; i < valuesSize(); i++) {
+            Value instr = valueAt(i);
             if (instr instanceof Phi && !instr.isDeadPhi()) {
                 Phi phi = (Phi) instr;
                 if (block == null || phi.block() == block) {
@@ -377,9 +379,8 @@
      * Checks whether this frame state has any {@linkplain Phi phi} statements.
      */
     public boolean hasPhis() {
-        int max = valuesSize();
-        for (int i = 0; i < max; i++) {
-            Value value = values[i];
+        for (int i = 0; i < valuesSize(); i++) {
+            Value value = valueAt(i);
             if (value instanceof Phi) {
                 return true;
             }
@@ -388,19 +389,6 @@
     }
 
     /**
-     * Iterates over all the values in this frame state and its callers, including the stack, locals, and locks.
-     * @param closure the closure to apply to each value
-     */
-    public void valuesDo(ValueClosure closure) {
-        for (int i = 0; i < values.length; i++) {
-            if (values[i] != null) {
-                Value newValue = closure.apply(values[i]);
-                values[i] = newValue;
-            }
-        }
-    }
-
-    /**
      * The interface implemented by a client of {@link FrameState#forEachLiveStateValue(ValueProcedure)}.
      */
     public static interface ValueProcedure {
@@ -413,9 +401,8 @@
      * @param proc the call back called to process each live value traversed
      */
     public final void forEachLiveStateValue(ValueProcedure proc) {
-        final int max = this.valuesSize();
-        for (int i = 0; i < max; i++) {
-            Value value = this.values[i];
+        for (int i = 0; i < valuesSize(); i++) {
+            Value value = valueAt(i);
             if (value != null) {
                 proc.doValue(value);
             }
@@ -441,4 +428,26 @@
         }
         return sb.toString();
     }
+
+    @Override
+    public BlockBegin block() {
+        return null;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitFrameState(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("FrameState");
+    }
+
+    @Override
+    public FrameState copy() {
+        return new FrameState(bci, localsSize, stackSize, locksSize, graph());
+    }
+
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Mon May 09 17:00:25 2011 +0200
@@ -34,7 +34,7 @@
 import static java.lang.reflect.Modifier.*;
 
 
-public class FrameStateBuilder {
+public class FrameStateBuilder implements FrameStateAccess {
 
     private final Graph graph;
 
@@ -75,12 +75,16 @@
     }
 
     public void initializeFrom(FrameState other) {
-        assert locals.length == other.localsSize;
+        assert locals.length == other.localsSize();
         assert stack.length >= other.stackSize();
 
         this.stackIndex = other.stackSize();
-        System.arraycopy(other.values, 0, locals, 0, locals.length);
-        System.arraycopy(other.values, other.localsSize(), stack, 0, stackIndex);
+        for (int i = 0; i < other.localsSize(); i++) {
+            locals[i] = other.localAt(i);
+        }
+        for (int i = 0; i < other.stackSize(); i++) {
+            stack[i] = other.stackAt(i);
+        }
         locks.clear();
         for (int i = 0; i < other.locksSize(); i++) {
             locks.add(other.lockAt(i));
@@ -88,7 +92,7 @@
     }
 
     public FrameState create(int bci) {
-        return new FrameState(bci, locals, stack, stackIndex, locks);
+        return new FrameState(bci, locals, stack, stackIndex, locks, graph);
     }
 
     /**
@@ -171,6 +175,12 @@
         xpush(null);
     }
 
+    public void pushReturn(CiKind kind, Value x) {
+        if (kind != CiKind.Void) {
+            push(kind.stackKind(), x);
+        }
+    }
+
     /**
      * Pops an instruction off the stack with the expected type.
      * @param kind the expected type
@@ -265,6 +275,16 @@
         return r;
     }
 
+    public CiKind peekKind() {
+        Value top = stackAt(stackSize() - 1);
+        if (top == null) {
+            top = stackAt(stackSize() - 2);
+            assert top != null;
+            assert top.kind.isDoubleWord();
+        }
+        return top.kind;
+    }
+
     /**
      * Truncates this stack to the specified size.
      * @param size the size to truncate to
@@ -434,4 +454,21 @@
 
     }
 
+
+    @Override
+    public FrameState duplicate() {
+        return create(-1);
+    }
+
+    @Override
+    public Value valueAt(int i) {
+        if (i < locals.length) {
+            return locals[i];
+        } else if (i < locals.length + stackIndex) {
+            return stack[i - locals.length];
+        } else {
+            return locks.get(i - locals.length - stack.length);
+        }
+    }
+
 }
--- a/graal/GraalGraph/src/com/oracle/graal/graph/Node.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalGraph/src/com/oracle/graal/graph/Node.java	Mon May 09 17:00:25 2011 +0200
@@ -75,6 +75,10 @@
         return graph;
     }
 
+    public String shortName() {
+        return getClass().getSimpleName();
+    }
+
     public void replace(Node other) {
         assert !isDeleted() && !other.isDeleted();
         assert other == null || other.graph == graph;
@@ -161,8 +165,7 @@
         }
 
         public Node set(int index, Node node) {
-            // TODO: re-enable after Value class layout changes
-//            assert node == Null || node.graph == self().graph;
+            assert node == Null || node.graph == self().graph;
             Node old = nodes[index];
 
             if (old != node) {
@@ -188,6 +191,13 @@
             return old;
         }
 
+        public void setAll(NodeArray other) {
+            assert size() == other.size();
+            for (int i = 0; i < other.size(); i++) {
+                set(i, other.get(i));
+            }
+        }
+
         public Node get(int index) {
             return nodes[index];
         }
--- a/graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java	Mon May 09 17:00:25 2011 +0200
@@ -77,23 +77,27 @@
     /**
      * Prints all nodes and edges in the specified graph.
      */
-    public void print(Graph graph) {
+    public void print(Graph graph, boolean shortNames) {
         // graph.getNodes() returns all the graph's nodes, not just "roots"
         for (Node n : graph.getNodes()) {
-            printNode(n);
+            printNode(n, shortNames);
         }
     }
 
     /**
      * Prints a single node and edges for all its inputs and successors.
      */
-    public void printNode(Node node) {
+    public void printNode(Node node, boolean shortNames) {
         int id = node.id();
         String name = "n" + id;
         NodeArray inputs = node.inputs();
         NodeArray successors = node.successors();
 
-        printNode(name, node.toString(), inputs.size(), successors.size());
+        if (shortNames) {
+            printNode(name, node.shortName(), inputs.size(), successors.size());
+        } else {
+            printNode(name, node.toString(), inputs.size(), successors.size());
+        }
 
         for (int i = 0; i < successors.size(); ++i) {
             Node successor = successors.get(i);
@@ -105,6 +109,9 @@
         for (int i = 0; i < inputs.size(); ++i) {
             Node input = inputs.get(i);
             if (input != Node.Null) {
+                if (node.getClass().getSimpleName().equals("FrameState") && input.getClass().getSimpleName().equals("Local")) {
+                    continue;
+                }
                 printDataEdge(id, i, input.id());
             }
         }
--- a/graal/GraalGraphviz/test/com/oracle/graal/graph/vis/GraphvizTest.java	Mon May 09 14:11:13 2011 +0200
+++ b/graal/GraalGraphviz/test/com/oracle/graal/graph/vis/GraphvizTest.java	Mon May 09 17:00:25 2011 +0200
@@ -67,7 +67,7 @@
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         GraphvizPrinter printer = new GraphvizPrinter(out);
         printer.begin("Simple test");
-        printer.print(g);
+        printer.print(g, false);
         printer.end();
 
         int exitCode = GraphvizRunner.process(GraphvizRunner.DOT_LAYOUT, new ByteArrayInputStream(out.toByteArray()), new NullOutputStream(), "xdot");
--- a/src/share/vm/runtime/arguments.cpp	Mon May 09 14:11:13 2011 +0200
+++ b/src/share/vm/runtime/arguments.cpp	Mon May 09 17:00:25 2011 +0200
@@ -2694,6 +2694,8 @@
       scp_p->add_prefix(temp);
       sprintf(temp, "%s/graal/GraalGraph/bin", graal_dir);
       scp_p->add_prefix(temp);
+      sprintf(temp, "%s/graal/GraalGraphviz/bin", graal_dir);
+      scp_p->add_prefix(temp);
       *scp_assembly_required_p = true;
     } else if (match_option(option, "-C1X:", &tail)) { // -C1X:xxxx
       // Option for the C1X compiler.