changeset 3012:4d03919746d4

merge
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 16 Jun 2011 20:43:51 +0200
parents f00918f35c7f (current diff) ac6fb0c93ffb (diff)
children 5ee0f57bb18c
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BlockEnd.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java
diffstat 50 files changed, 468 insertions(+), 550 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Thu Jun 16 20:43:51 2011 +0200
@@ -28,6 +28,7 @@
 import com.oracle.max.graal.compiler.globalstub.*;
 import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.target.*;
+import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 import com.sun.cri.xir.*;
@@ -58,6 +59,8 @@
 
     public final RiRegisterConfig globalStubRegisterConfig;
 
+    private GraalCompilation currentCompilation;
+
     public GraalCompiler(RiRuntime runtime, CiTarget target, RiXirGenerator xirGen, RiRegisterConfig globalStubRegisterConfig) {
         this.runtime = runtime;
         this.target = target;
@@ -65,6 +68,17 @@
         this.globalStubRegisterConfig = globalStubRegisterConfig;
         this.backend = Backend.create(target.arch, this);
         init();
+
+        Graph.verificationListeners.add(new VerificationListener() {
+            @Override
+            public void verificationFailed(Node n) {
+                GraalCompiler.this.fireCompilationEvent(new CompilationEvent(currentCompilation, "Verification Error on Node " + n.id(), currentCompilation.graph, true, false));
+                for (Node p : n.predecessors()) {
+                    TTY.println("predecessor: " + p);
+                }
+                assert false : "Verification of node " + n + " failed";
+            }
+        });
     }
 
     public CiResult compileMethod(RiMethod method, int osrBCI, RiXirGenerator xirGenerator, CiStatistics stats) {
@@ -78,6 +92,7 @@
         CiResult result = null;
         TTY.Filter filter = new TTY.Filter(GraalOptions.PrintFilter, method);
         GraalCompilation compilation = new GraalCompilation(this, method, osrBCI, stats);
+        currentCompilation = compilation;
         try {
             result = compilation.compile();
         } finally {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalMetrics.java	Thu Jun 16 20:43:51 2011 +0200
@@ -65,11 +65,10 @@
     public static int NodesCanonicalized;
 
     public static void print() {
-        printClassFields(GraalMetrics.class);
-
         for (Entry<String, GraalMetrics> m : map.entrySet()) {
             printField(m.getKey(), m.getValue().value);
         }
+        printClassFields(GraalMetrics.class);
     }
 
     private static LinkedHashMap<String, GraalMetrics> map = new LinkedHashMap<String, GraalMetrics>();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java	Thu Jun 16 20:43:51 2011 +0200
@@ -105,7 +105,7 @@
         assert instructions.get(0).code == LIROpcode.Label : "first instruction must always be a label";
         assert instructions.get(instructions.size() - 1) instanceof LIRBranch : "last instruction must always be a branch but is " + instructions.get(instructions.size() - 1);
         assert ((LIRBranch) instructions.get(instructions.size() - 1)).cond() == Condition.TRUE : "branch must be unconditional";
-        assert ((LIRBranch) instructions.get(instructions.size() - 1)).block() == block.suxAt(0) : "branch target must be the successor";
+        assert ((LIRBranch) instructions.get(instructions.size() - 1)).block() == block.suxAt(0) : "branch target must be the successor " + ((LIRBranch) instructions.get(instructions.size() - 1)).block();
 
         // block must have exactly one successor
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java	Thu Jun 16 20:43:51 2011 +0200
@@ -25,10 +25,8 @@
 import java.util.*;
 
 import com.oracle.max.graal.compiler.*;
-import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.graph.*;
 
 /**
  * This class optimizes moves, particularly those that result from eliminating SSA form.
@@ -193,11 +191,6 @@
 
         assert numSux == 2 : "method should not be called otherwise";
 
-        if ( instructions.get(instructions.size() - 1).code != LIROpcode.Branch) {
-            for (Node n : block.getInstructions()) {
-                TTY.println("instr: " + n);
-            }
-        }
         assert instructions.get(instructions.size() - 1).code == LIROpcode.Branch : "block with successor must end with branch block=B" + block.blockID();
         assert instructions.get(instructions.size() - 1) instanceof LIRBranch : "branch must be LIROpBranch";
         assert ((LIRBranch) instructions.get(instructions.size() - 1)).cond() == Condition.TRUE : "block must end with unconditional branch";
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Thu Jun 16 20:43:51 2011 +0200
@@ -236,8 +236,8 @@
                 }
                 if (node instanceof Merge) {
                     Merge merge = (Merge) node;
-                    if (merge.stateBefore() != null) {
-                        nodes.add(merge.stateBefore());
+                    if (merge.stateAfter() != null) {
+                        nodes.add(merge.stateAfter());
                     }
                     for (Node usage : merge.usages()) {
                         if (usage instanceof Phi || usage instanceof LoopCounter) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Jun 16 20:43:51 2011 +0200
@@ -240,19 +240,6 @@
             if (instr instanceof Instruction) {
                 stateAfter = ((Instruction) instr).stateAfter();
             }
-            FrameState stateBefore = null;
-            if (instr instanceof StateSplit && ((StateSplit) instr).stateBefore() != null) {
-                stateBefore = ((StateSplit) instr).stateBefore();
-            }
-            if (stateBefore != null) {
-                lastState = stateBefore;
-                if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
-                    TTY.println("STATE CHANGE (stateBefore)");
-                    if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
-                        TTY.println(stateBefore.toString());
-                    }
-                }
-            }
             if (instr != instr.graph().start()) {
                 walkState(instr, stateAfter);
                 doRoot((Value) instr);
@@ -267,7 +254,7 @@
                 }
             }
         }
-        if (block.blockSuccessors().size() >= 1 && !jumpsToNextBlock(block.lastInstruction())) {
+        if (block.blockSuccessors().size() >= 1 && !block.endsWithJump()) {
             block.lir().jump(getLIRBlock((FixedNode) block.lastInstruction().successors().get(0)));
         }
 
@@ -285,10 +272,6 @@
         // Nothing to do.
     }
 
-    private static boolean jumpsToNextBlock(Node node) {
-        return node instanceof BlockEnd || node instanceof EndNode || node instanceof LoopEnd;
-    }
-
     @Override
     public void visitArrayLength(ArrayLength x) {
         emitArrayLength(x);
@@ -718,6 +701,10 @@
     @Override
     public void visitFixedGuard(FixedGuard fixedGuard) {
         Node comp = fixedGuard.node();
+        emitGuardComp(comp);
+    }
+
+    public void emitGuardComp(Node comp) {
         if (comp instanceof IsNonNull) {
             IsNonNull x = (IsNonNull) comp;
             CiValue value = load(x.object());
@@ -725,7 +712,7 @@
             lir.nullCheck(value, info);
         } else if (comp instanceof IsType) {
             IsType x = (IsType) comp;
-            CiValue value = load(x.object());
+            load(x.object());
             LIRDebugInfo info = stateFor(x);
             XirArgument clazz = toXirArgument(x.type().getEncoding(Representation.ObjectHub));
             XirSnippet typeCheck = xir.genTypeCheck(site(x), toXirArgument(x.object()), clazz, x.type());
@@ -981,10 +968,9 @@
             if (rangeDensity >= GraalOptions.RangeTestsSwitchDensity) {
                 visitSwitchRanges(switchRanges, tag, getLIRBlock(x.defaultSuccessor()));
             } else {
-                List<Instruction> nonDefaultSuccessors = x.blockSuccessors().subList(0, x.numberOfCases());
-                LIRBlock[] targets = new LIRBlock[nonDefaultSuccessors.size()];
-                for (int i = 0; i < nonDefaultSuccessors.size(); ++i) {
-                    targets[i] = getLIRBlock(nonDefaultSuccessors.get(i));
+                LIRBlock[] targets = new LIRBlock[x.numberOfCases()];
+                for (int i = 0; i < x.numberOfCases(); ++i) {
+                    targets[i] = getLIRBlock(x.blockSuccessor(i));
                 }
                 lir.tableswitch(tag, x.lowKey(), getLIRBlock(x.defaultSuccessor()), targets);
             }
@@ -1107,7 +1093,7 @@
     @Override
     public void visitRegisterFinalizer(RegisterFinalizer x) {
         CiValue receiver = load(x.object());
-        LIRDebugInfo info = stateFor(x, x.stateBefore());
+        LIRDebugInfo info = stateFor(x);
         callRuntime(CiRuntimeCall.RegisterFinalizer, info, receiver);
         setNoResult(x);
     }
@@ -1433,10 +1419,19 @@
     public void visitEndNode(EndNode end) {
         setNoResult(end);
         Merge merge = end.merge();
+        assert merge != null;
         moveToPhi(merge, merge.endIndex(end));
         lir.jump(getLIRBlock(end.merge()));
     }
 
+    @Override
+    public void visitMemoryRead(MemoryRead memRead) {
+        if (memRead.guard() != null) {
+            emitGuardComp(memRead.guard());
+        }
+        lir.move(new CiAddress(memRead.valueKind(), load(memRead.location()), memRead.displacement()), createResultVariable(memRead), memRead.valueKind());
+    }
+
 
     @Override
     public void visitLoopEnd(LoopEnd x) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/package-info.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/package-info.java	Thu Jun 16 20:43:51 2011 +0200
@@ -27,128 +27,5 @@
  * The {@link com.oracle.max.graal.compiler.graph.IR} class drives the generation of the HIR graph for a method, making use of other
  * utility classes in this package.
  *
- * The graph building is separated into a basic build phase ({@link com.oracle.max.graal.compiler.graph.IR#buildGraph} method)and
- * (currently) two optimization phases ({@link com.oracle.max.graal.compiler.graph.IR#optimize1} and
- * {@link com.oracle.max.graal.compiler.graph.IR#optimize2}) although the basic phase also does some (basic) optimizations.
- *
- * <H2>Basic Graph Build Phase</H2>
- *
- * {@code IR.buildGraph} creates an {@link com.oracle.max.graal.compiler.ir.IRScope topScope} object,
- * that represents a context for inlining, and then invokes the constructor for the
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase} class, passing the {@link com.oracle.max.graal.compiler.GraalCompilation}, and {@code IR}
- * instances, which are cached. The following support objects are created in the constructor:
- *
- * <ul>
- * <li>{@code memoryMap}: an instance of {@link com.oracle.max.graal.compiler.graph.MemoryMap}
- * <li>{@code localValueMap}: an instance of {@link com.oracle.max.graal.compiler.opt.ValueMap}
- * <li>{@code canonicalizer}: an instance of {@link com.oracle.max.graal.compiler.opt.Canonicalizer}
- * </ul>
- *
- * Now the {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#build} is invoked with {@code topScope} as argument.
- *
- * <H3>{@code GraphBuilder.build}</H3>
- *
- * <ol>
- * <li>The {@link com.oracle.max.graal.compiler.graph.IR#startBlock} field of the cached {@link com.oracle.max.graal.compiler.graph.IR} instance is set to a newly created
- * {@link com.oracle.max.graal.compiler.ir.BlockBegin} node, with bytecode index 0 and then the {@link com.oracle.max.graal.compiler.graph.BlockMap} is
- * constructed by calling {@link com.oracle.max.graal.compiler.GraalCompilation#getBlockMap}. This behaves slightly differently depending on
- * whether this is an OSR compilation. If so, a new {@link com.oracle.max.graal.compiler.ir.BlockBegin} node is added to the map at the OSR bytecode
- * index. The map is then built by the{@link com.oracle.max.graal.compiler.graph.BlockMap#build}, which takes a boolean argument that
- * controls whether a second pass is made over the bytecodes to compute stores in loops. This always false for an OSR
- * compilation (why?). Otherwise, it is only true if enabled by the {@link com.oracle.max.graal.compiler.GraalOptions#PhiLoopStores}
- * compilation option. FInally some unneeded state from the map is removed by the {@link com.oracle.max.graal.compiler.graph.BlockMap#cleanup} method, and
- * the statistics are updated.
- * </li>
- *
- * <li>Next the {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#pushRootScope} method is called, with the passed-in {@link com.oracle.max.graal.compiler.ir.IRScope}
- * object, the {@link com.oracle.max.graal.compiler.graph.BlockMap} returned by build and the {@code startBlock}. (Note: Unlike
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#pushScope}, this method does not propagate the
- * {@link com.oracle.max.graal.compiler.graph.BlockMap#storesInLoops} field to the {@link com.oracle.max.graal.compiler.ir.IRScope} object, which means that
- * {@link com.oracle.max.graal.compiler.ir.BlockBegin#insertLoopPhis} will always get null for this value. Is this a bug?).
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#pushRootScope} initializes the {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#scopeData} field with a
- * {@link com.oracle.max.graal.compiler.graph.ScopeData} instance, with null parent. The
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#compilation} instance is called to get an {@link com.sun.cri.ri.RiConstantPool}
- * , which is Graal's interface to constant pool information. The {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curBlock} field is
- * set to the {@code startBlock}.
- * <p>
- *
- * Now a {@link com.oracle.max.graal.compiler.value.FrameState initialState} object is created by
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#stateAtEntry}. If the method is not static, then a {@link com.oracle.max.graal.compiler.ir.Local}
- * instance is created at index 0. Since the receiver cannot be {@code null}, the
- * {@link com.oracle.max.graal.compiler.ir.Value.Flag#NonNull} flag is set. Additional {@link com.oracle.max.graal.compiler.ir.Local} instances are created for the
- * arguments to the method. The index is incremented by the number of slots occupied by the
- * {@link com.sun.cri.ci.CiKind} corresponding to the argument type. All the {@link com.oracle.max.graal.compiler.ir.Local} instances are stored in the
- * {@link com.oracle.max.graal.compiler.value.FrameState} using the {@link com.oracle.max.graal.compiler.value.FrameState#storeLocal} method. This {@link com.oracle.max.graal.compiler.value.FrameState} is then
- * merged into the {@link com.oracle.max.graal.compiler.ir.BlockBegin#stateBefore} for the {@code startBlock}, which just results in a
- * copy since {@code stateBefore} will be {@code null}.
- * </li>
- * <li>
- * This step sets up three instance fields: {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curBlock} and
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#lastInstr} to {@code startBlock} and
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curState} to {@code initialState}. (N.B. the setting of {@code curBlock} is
- * redundant as it is done in {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#pushRootScope}).
- * </li>
- * <li>
- * Step 4 contains special handling for synchronized methods (TBD), otherwise it calls
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#finishStartBlock} which adds a {@link com.oracle.max.graal.compiler.ir.Base} block as the end of
- * the {@code startBlock}. The {@link com.oracle.max.graal.compiler.ir.Base} block has one successor set to the (entry) block with flag
- * {@link com.oracle.max.graal.compiler.ir.BlockBegin.BlockFlag#StandardEntry}, that was created by {@link com.oracle.max.graal.compiler.graph.BlockMap#build} (and possibly a
- * successor to an OSREntry block).
- * </li>
- * <li>
- * Then the {@link com.oracle.max.graal.compiler.ir.IRScope#lockStackSize} is computed. (TBD)
- * </li>
- * <li>
- * Then the method is checked for being intrinsic, i.e., one that has a hard-wired implementation known to Graal. If so,
- * and {@link com.oracle.max.graal.compiler.GraalOptions#OptIntrinsify} is set, an attempt is made to inline it (TBD). Otherwise, or if the
- * intrinsification fails, normal processing continues by adding the entry block to the
- * {@link com.oracle.max.graal.compiler.graph.ScopeData} work list (kept topologically sorted) and calling
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#iterateAllBlocks}.
- * </li>
- * <li>
- * Finally there is some cleanup code for synchronized blocks and OSR compilations.
- * </li>
- * </ol>
- *
- * <H3>{@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#iterateAllBlocks}</H3>
- * {@link com.oracle.max.graal.compiler.graph#iterateAllBlocks} repeatedly removes a block from the work list and, if not already visited, marks it so,
- * kills the current memory map, sets {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curBlock}, {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curState}
- * and {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#lastInstr} and then calls
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#iterateBytecodesForBlock}.
- *
- * This process continues until all the blocks have been visited (processed) after which control returns to {@code
- * build}.
- * <p>
-
- * <H3>{@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#iterateBytecodesForBlock}</H3>
- *
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#iterateBytecodesForBlock} performs an abstract interpretation of the bytecodes in the block, appending new
- * nodes as necessary, until the last added node is an instance of {@link com.oracle.max.graal.compiler.ir.BlockEnd}. (Note: It has an
- * explicit check for finding a new {@link com.oracle.max.graal.compiler.ir.BlockBegin} before a {@link com.oracle.max.graal.compiler.ir.BlockEnd} but
- * {@link com.oracle.max.graal.compiler.graph.BlockMap#moveSuccessorLists} has a similar check so this may be redundant). For example,
- * consider the following bytecodes:
- *
- * <pre>
- * <code>
- *         0: iconst_0
- *         1: istore_2
- *         2: goto 22
- * </code>
- * </pre>
- *
- * The {@code iconst_0} bytecode causes a {@link com.oracle.max.graal.compiler.ir.Constant} node representing zero to be pushed on the
- * {@link com.oracle.max.graal.compiler.phases.GraphBuilderPhase#curState} stack and the node to be appended to the {@link com.oracle.max.graal.compiler.ir.BlockBegin} (entry) node associated with index 0.
- * The {@code istore_2} causes the node to be popped of the stack and stored in the local slot 2. No IR node is
- * generated for the {@code istore_2}. The {@code goto} creates a {@link com.oracle.max.graal.compiler.ir.Goto} node which is a subclass
- * of {@link com.oracle.max.graal.compiler.ir.BlockEnd}, so this terminates the iteration. As part of termination the {@link com.oracle.max.graal.compiler.ir.Goto} node is marked as the
- * end node of the current block and the {@link com.oracle.max.graal.compiler.value.FrameState} is propagated to the successor node(s) by merging any
- * existing {@link com.oracle.max.graal.compiler.value.FrameState} with the current state. If the target is a loop header node this involves inserting
- * {@link com.oracle.max.graal.compiler.ir.Phi} nodes. Finally, the target node is added to the {@code scopeData} work list.
- * <p>
- *
- *
- * @author Ben Titzer
- * @author Mick Jordan
- *
  */
 package com.oracle.max.graal.compiler.graph;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessArray.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessArray.java	Thu Jun 16 20:43:51 2011 +0200
@@ -60,7 +60,6 @@
      * Creates a new AccessArray instruction.
      * @param kind the type of the result of this instruction
      * @param array the instruction that produces the array object value
-     * @param stateBefore the frame state before the instruction
      * @param inputCount
      * @param successorCount
      * @param graph
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessIndexed.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessIndexed.java	Thu Jun 16 20:43:51 2011 +0200
@@ -78,7 +78,6 @@
      * @param index the instruction producing the index
      * @param length the instruction producing the length (used in bounds check elimination?)
      * @param elementKind the type of the elements of the array
-     * @param stateBefore the state before executing this instruction
      * @param inputCount
      * @param successorCount
      * @param graph
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessMonitor.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessMonitor.java	Thu Jun 16 20:43:51 2011 +0200
@@ -78,7 +78,6 @@
      *
      * @param object the instruction producing the object
      * @param lockAddress the address of the on-stack lock object or {@code null} if the runtime does not place locks on the stack
-     * @param stateBefore the state before executing the monitor operation
      * @param lockNumber the number of the lock being acquired
      * @param inputCount
      * @param successorCount
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Arithmetic.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Arithmetic.java	Thu Jun 16 20:43:51 2011 +0200
@@ -44,7 +44,6 @@
      * @param x the first input instruction
      * @param y the second input instruction
      * @param isStrictFP indicates this operation has strict rounding semantics
-     * @param stateBefore the state for instructions that may trap
      */
     public Arithmetic(CiKind kind, int opcode, Value x, Value y, boolean isStrictFP, Graph graph) {
         super(kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BlockEnd.java	Thu Jun 16 20:36:17 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.ir;
-
-import java.util.*;
-
-import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
-
-/**
- * The {@code BlockEnd} instruction is a base class for all instructions that end a basic
- * block, including branches, switches, throws, and goto's.
- */
-public abstract class BlockEnd extends Instruction {
-
-    private static final int INPUT_COUNT = 0;
-
-    private static final int SUCCESSOR_COUNT = 0;
-    private final int blockSuccessorCount;
-
-    @Override
-    protected int inputCount() {
-        return super.inputCount() + INPUT_COUNT;
-    }
-
-    @Override
-    protected int successorCount() {
-        return super.successorCount() + blockSuccessorCount + SUCCESSOR_COUNT;
-    }
-
-    /**
-     * The list of instructions that produce input for this instruction.
-     */
-    public FixedNode blockSuccessor(int index) {
-        assert index >= 0 && index < blockSuccessorCount;
-        return (FixedNode) successors().get(super.successorCount() + SUCCESSOR_COUNT + index);
-    }
-
-    public FixedNode setBlockSuccessor(int index, FixedNode n) {
-        assert index >= 0 && index < blockSuccessorCount;
-        return (FixedNode) successors().set(super.successorCount() + SUCCESSOR_COUNT + index, n);
-    }
-
-    public int blockSuccessorCount() {
-        return blockSuccessorCount;
-    }
-
-    /**
-     * Constructs a new block end with the specified value type.
-     * @param kind the type of the value produced by this instruction
-     * @param successors the list of successor blocks. If {@code null}, a new one will be created.
-     */
-    public BlockEnd(CiKind kind, List<? extends Instruction> blockSuccessors, int inputCount, int successorCount, Graph graph) {
-        this(kind, blockSuccessors.size(), inputCount, successorCount, graph);
-        for (int i = 0; i < blockSuccessors.size(); i++) {
-            setBlockSuccessor(i, blockSuccessors.get(i));
-        }
-    }
-
-    public BlockEnd(CiKind kind, int blockSuccessorCount, int inputCount, int successorCount, Graph graph) {
-        super(kind, inputCount + INPUT_COUNT, successorCount + blockSuccessorCount + SUCCESSOR_COUNT, graph);
-        this.blockSuccessorCount = blockSuccessorCount;
-    }
-
-    public BlockEnd(CiKind kind, Graph graph) {
-        this(kind, 2, 0, 0, graph);
-    }
-
-    /**
-     * Substitutes a successor block in this block end's successor list. Note that
-     * this method updates all occurrences in the list.
-     * @param oldSucc the old successor to replace
-     * @param newSucc the new successor
-     */
-    public int substituteSuccessor(Merge oldSucc, Merge newSucc) {
-        assert newSucc != null;
-        int count = 0;
-        for (int i = 0; i < blockSuccessorCount; i++) {
-            if (blockSuccessor(i) == oldSucc) {
-                setBlockSuccessor(i, newSucc);
-                count++;
-            }
-        }
-        return count;
-    }
-
-    /**
-     * Gets the successor corresponding to the default (fall through) case.
-     * @return the default successor
-     */
-    public FixedNode defaultSuccessor() {
-        return blockSuccessor(blockSuccessorCount - 1);
-    }
-
-    /**
-     * Searches for the specified successor and returns its index into the
-     * successor list if found.
-     * @param b the block to search for in the successor list
-     * @return the index of the block in the list if found; <code>-1</code> otherwise
-     */
-    public int successorIndex(Merge b) {
-        for (int i = 0; i < blockSuccessorCount; i++) {
-            if (blockSuccessor(i) == b) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Gets this block end's list of successors.
-     * @return the successor list
-     */
-    @SuppressWarnings({ "unchecked", "rawtypes"})
-    public List<Instruction> blockSuccessors() {
-        List<Instruction> list = (List) successors().subList(super.successorCount() + SUCCESSOR_COUNT, super.successorCount() + blockSuccessorCount + SUCCESSOR_COUNT);
-        return Collections.unmodifiableList(list);
-    }
-
-    public void clearSuccessors() {
-        for (int i = 0; i < blockSuccessorCount(); i++) {
-            setBlockSuccessor(i, null);
-        }
-    }
-
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java	Thu Jun 16 20:43:51 2011 +0200
@@ -41,7 +41,6 @@
      * 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, Graph graph) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ControlSplit.java	Thu Jun 16 20:43:51 2011 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+/**
+ * The {@code BlockEnd} instruction is a base class for all instructions that end a basic
+ * block, including branches, switches, throws, and goto's.
+ */
+public abstract class ControlSplit extends FixedNode {
+
+    private static final int INPUT_COUNT = 0;
+
+    private static final int SUCCESSOR_COUNT = 0;
+    private final int blockSuccessorCount;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + blockSuccessorCount + SUCCESSOR_COUNT;
+    }
+
+    /**
+     * The list of instructions that produce input for this instruction.
+     */
+    public FixedNode blockSuccessor(int index) {
+        assert index >= 0 && index < blockSuccessorCount;
+        return (FixedNode) successors().get(super.successorCount() + SUCCESSOR_COUNT + index);
+    }
+
+    public FixedNode setBlockSuccessor(int index, FixedNode n) {
+        assert index >= 0 && index < blockSuccessorCount;
+        return (FixedNode) successors().set(super.successorCount() + SUCCESSOR_COUNT + index, n);
+    }
+
+    public int blockSuccessorCount() {
+        return blockSuccessorCount;
+    }
+
+    /**
+     * Constructs a new block end with the specified value type.
+     * @param kind the type of the value produced by this instruction
+     * @param successors the list of successor blocks. If {@code null}, a new one will be created.
+     */
+    public ControlSplit(CiKind kind, List<? extends FixedNode> blockSuccessors, int inputCount, int successorCount, Graph graph) {
+        this(kind, blockSuccessors.size(), inputCount, successorCount, graph);
+        for (int i = 0; i < blockSuccessors.size(); i++) {
+            setBlockSuccessor(i, blockSuccessors.get(i));
+        }
+    }
+
+    public ControlSplit(CiKind kind, int blockSuccessorCount, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + blockSuccessorCount + SUCCESSOR_COUNT, graph);
+        this.blockSuccessorCount = blockSuccessorCount;
+    }
+
+    /**
+     * Gets the successor corresponding to the default (fall through) case.
+     * @return the default successor
+     */
+    public FixedNode defaultSuccessor() {
+        return blockSuccessor(blockSuccessorCount - 1);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Thu Jun 16 20:43:51 2011 +0200
@@ -28,7 +28,7 @@
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 
-public class Deoptimize extends Instruction {
+public class Deoptimize extends FixedNode {
 
     private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Thu Jun 16 20:43:51 2011 +0200
@@ -57,4 +57,13 @@
             return (Merge) usages().get(0);
         }
     }
+
+    @Override
+    public boolean verify() {
+        assertTrue(inputs().size() == 0);
+        assertTrue(successors().size() == 0);
+        assertTrue(usages().size() <= 1);
+        assertTrue(predecessors().size() <= 1);
+        return true;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java	Thu Jun 16 20:43:51 2011 +0200
@@ -31,7 +31,7 @@
  * This instruction takes an exception object and has two successors:
  * The catchSuccessor is called whenever the exception matches the given type, otherwise otherSuccessor is called.
  */
-public final class ExceptionDispatch extends BlockEnd {
+public final class ExceptionDispatch extends ControlSplit {
 
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_EXCEPTION = 0;
@@ -115,9 +115,9 @@
         print(' ').
         print(catchType().name()).
         print(" then ").
-        print(blockSuccessors().get(1).toString()).
+        print(catchSuccessor().toString()).
         print(" else B").
-        print(blockSuccessors().get(0).toString());
+        print(otherSuccessor().toString());
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionObject.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionObject.java	Thu Jun 16 20:43:51 2011 +0200
@@ -36,7 +36,6 @@
 
     /**
      * Constructs a new ExceptionObject instruction.
-     * @param stateBefore TODO
      * @param graph
      */
     public ExceptionObject(Graph graph) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Thu Jun 16 20:43:51 2011 +0200
@@ -30,7 +30,7 @@
  * The {@code If} instruction represents a branch that can go one of two directions
  * depending on the outcome of a comparison.
  */
-public final class If extends BlockEnd {
+public final class If extends ControlSplit {
 
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_COMPARE = 0;
@@ -102,9 +102,9 @@
         print(' ').
         print(compare().y()).
         print(" then ").
-        print(blockSuccessors().get(0)).
+        print(trueSuccessor()).
         print(" else ").
-        print(blockSuccessors().get(1));
+        print(falseSuccessor());
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Invoke.java	Thu Jun 16 20:43:51 2011 +0200
@@ -94,7 +94,6 @@
      * @param args the list of instructions producing arguments to the invocation, including the receiver object
      * @param isStatic {@code true} if this call is static (no receiver object)
      * @param target the target method being called
-     * @param stateBefore the state before executing the invocation
      */
     public Invoke(int bci, int opcode, CiKind result, Value[] args, RiMethod target, RiType returnType, RiTypeProfile profile, Graph graph) {
         super(result, args.length, SUCCESSOR_COUNT, graph);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java	Thu Jun 16 20:43:51 2011 +0200
@@ -63,7 +63,6 @@
     /**
      * Constructs a new NullCheck instruction.
      * @param object the instruction producing the object to check against null
-     * @param stateBefore the state before executing the null check
      * @param graph
      */
     public IsNonNull(Value object, Graph graph) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java	Thu Jun 16 20:43:51 2011 +0200
@@ -36,6 +36,7 @@
  */
 public final class LoadField extends AccessField {
     private static final LoadFieldCanonicalizerOp CANONICALIZER = new LoadFieldCanonicalizerOp();
+    private static final LoadFieldLoweringOp LOWERING = new LoadFieldLoweringOp();
 
     private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
@@ -118,6 +119,8 @@
     public <T extends Op> T lookup(Class<T> clazz) {
         if (clazz == CanonicalizerOp.class) {
             return (T) CANONICALIZER;
+        } else if (clazz == LoweringOp.class) {
+            return (T) LOWERING;
         }
         return super.lookup(clazz);
     }
@@ -127,7 +130,17 @@
         @Override
         public Node lower(Node n, LoweringTool tool) {
             LoadField field = (LoadField) n;
-            return null; //field.field().createLoad(tool);
+            if (field.isVolatile()) {
+                return null;
+            }
+            Graph graph = field.graph();
+            int displacement = field.field().offset();
+            assert field.kind != CiKind.Illegal;
+            MemoryRead memoryRead = new MemoryRead(field.field().kind(), displacement, graph);
+            memoryRead.setGuard(new IsNonNull(field.object(), graph));
+            memoryRead.setNext(field.next());
+            memoryRead.setLocation(field.object());
+            return memoryRead;
         }
 
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LookupSwitch.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LookupSwitch.java	Thu Jun 16 20:43:51 2011 +0200
@@ -48,7 +48,7 @@
      * @param stateAfter the state after the switch
      * @param graph
      */
-    public LookupSwitch(Value value, List<? extends Instruction> successors, int[] keys, Graph graph) {
+    public LookupSwitch(Value value, List<? extends FixedNode> successors, int[] keys, Graph graph) {
         super(value, successors, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.keys = keys;
     }
@@ -78,7 +78,7 @@
         int l = numberOfCases();
         for (int i = 0; i < l; i++) {
             INSTRUCTION.advance(out);
-            out.printf("case %5d: B%d%n", keyAt(i), blockSuccessors().get(i));
+            out.printf("case %5d: B%d%n", keyAt(i), blockSuccessor(i));
         }
         INSTRUCTION.advance(out);
         out.print("default   : ").print(defaultSuccessor());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryRead.java	Thu Jun 16 20:43:51 2011 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class MemoryRead extends Instruction {
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_NODE = 0;
+    private static final int INPUT_GUARD = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private int displacement;
+    private CiKind valueKind;
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value location() {
+        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public Value setLocation(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public FloatingNode guard() {
+        return (FloatingNode) inputs().get(super.inputCount() + INPUT_GUARD);
+    }
+
+    public FloatingNode setGuard(FloatingNode n) {
+        return (FloatingNode) inputs().set(super.inputCount() + INPUT_GUARD, n);
+    }
+
+    public int displacement() {
+        return displacement;
+    }
+
+    public CiKind valueKind() {
+        return valueKind;
+    }
+
+    public MemoryRead(CiKind kind, int displacement, Graph graph) {
+        super(kind.stackKind(), INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        this.displacement = displacement;
+        this.valueKind = kind;
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMemoryRead(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("mem read from ").print(location());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new MemoryRead(super.kind, displacement(), into);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Thu Jun 16 20:43:51 2011 +0200
@@ -160,7 +160,7 @@
         boolean hasPhisOnStack = false;
 
         //if (end() != null && end().stateAfter() != null) {
-            FrameState state = stateBefore();
+            FrameState state = stateAfter();
 
             int i = 0;
             while (!hasPhisOnStack && i < state.stackSize()) {
@@ -213,8 +213,8 @@
             out.println();
             out.println("Stack:");
             int j = 0;
-            while (j < stateBefore().stackSize()) {
-                Value value = stateBefore().stackAt(j);
+            while (j < stateAfter().stackSize()) {
+                Value value = stateAfter().stackAt(j);
                 if (value != null) {
                     out.println(stateString(j, value));
                     j += value.kind.sizeInSlots();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewArray.java	Thu Jun 16 20:43:51 2011 +0200
@@ -59,7 +59,6 @@
     /**
      * 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
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Thu Jun 16 20:43:51 2011 +0200
@@ -43,7 +43,6 @@
      * Constructs a NewInstance instruction.
      * @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, Graph graph) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewMultiArray.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewMultiArray.java	Thu Jun 16 20:43:51 2011 +0200
@@ -75,7 +75,6 @@
      * Constructs a new NewMultiArray instruction.
      * @param elementType the element type of the array
      * @param dimensions the instructions which produce the dimensions for this array
-     * @param stateBefore the state before this instruction
      * @param cpi the constant pool index for resolution
      * @param riConstantPool the constant pool for resolution
      * @param graph
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java	Thu Jun 16 20:43:51 2011 +0200
@@ -23,14 +23,13 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
-import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
 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 {
+public final class RegisterFinalizer extends StateSplit {
 
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_OBJECT = 0;
@@ -58,10 +57,9 @@
         return (Value) inputs().set(super.inputCount() + INPUT_OBJECT, n);
     }
 
-    public RegisterFinalizer(Value object, FrameState stateBefore, Graph graph) {
+    public RegisterFinalizer(Value object, Graph graph) {
         super(CiKind.Void, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setObject(object);
-        setStateBefore(stateBefore);
     }
 
     @Override
@@ -76,7 +74,6 @@
 
     @Override
     public Node copy(Graph into) {
-        RegisterFinalizer x = new RegisterFinalizer(null, null, into);
-        return x;
+        return new RegisterFinalizer(null, into);
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Return.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Return.java	Thu Jun 16 20:43:51 2011 +0200
@@ -29,7 +29,7 @@
 /**
  * The {@code Return} class definition.
  */
-public final class Return extends BlockEnd {
+public final class Return extends FixedNode {
 
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_RESULT = 0;
@@ -58,11 +58,6 @@
         return (Value) inputs().set(super.inputCount() + INPUT_RESULT, n);
     }
 
-    @Override
-    public Instruction next() {
-        return null;
-    }
-
     /**
      * Constructs a new Return instruction.
      * @param result the instruction producing the result for this return; {@code null} if this
@@ -70,13 +65,13 @@
      * @param graph
      */
     public Return(Value result, Graph graph) {
-        super(result == null ? CiKind.Void : result.kind, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(result == null ? CiKind.Void : result.kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setResult(result);
     }
 
     // for copying
     private Return(CiKind kind, Graph graph) {
-        super(kind, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StateSplit.java	Thu Jun 16 20:43:51 2011 +0200
@@ -33,10 +33,9 @@
 public abstract class StateSplit extends Instruction {
 
     private static final int INPUT_COUNT = 1;
-    private static final int INPUT_STATE_BEFORE = 0;
+    private static final int INPUT_STATE_AFTER = 0;
 
     private static final int SUCCESSOR_COUNT = 1;
-    private static final int SUCCESSOR_STATE_AFTER = 0;
 
     @Override
     protected int inputCount() {
@@ -51,31 +50,13 @@
     /**
      * The state for this instruction.
      */
-    public FrameState stateBefore() {
-        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_BEFORE);
-    }
-
-    public FrameState setStateBefore(FrameState n) {
-        FrameState oldState = stateBefore();
-        try {
-            return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_BEFORE, n);
-        } finally {
-            if (oldState != n && oldState != null) {
-                oldState.delete();
-            }
-        }
-    }
-
-    /**
-     * The state for this instruction.
-     */
      @Override
     public FrameState stateAfter() {
-        return (FrameState) successors().get(super.successorCount() + SUCCESSOR_STATE_AFTER);
+        return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER);
     }
 
     public FrameState setStateAfter(FrameState n) {
-        return (FrameState) successors().set(super.successorCount() + SUCCESSOR_STATE_AFTER, n);
+        return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_AFTER, n);
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Switch.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Switch.java	Thu Jun 16 20:43:51 2011 +0200
@@ -30,7 +30,7 @@
 /**
  * The {@code Switch} class is the base of both lookup and table switches.
  */
-public abstract class Switch extends BlockEnd {
+public abstract class Switch extends ControlSplit {
 
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_VALUE = 0;
@@ -65,7 +65,7 @@
      * @param stateAfter the state after the switch
      * @param graph
      */
-    public Switch(Value value, List<? extends Instruction> successors, int inputCount, int successorCount, Graph graph) {
+    public Switch(Value value, List<? extends FixedNode> successors, int inputCount, int successorCount, Graph graph) {
         super(CiKind.Illegal, successors, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
         setValue(value);
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TableSwitch.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TableSwitch.java	Thu Jun 16 20:43:51 2011 +0200
@@ -47,7 +47,7 @@
      * @param stateAfter the state after the switch
      * @param graph
      */
-    public TableSwitch(Value value, List<? extends Instruction> successors, int lowKey, Graph graph) {
+    public TableSwitch(Value value, List<? extends FixedNode> successors, int lowKey, Graph graph) {
         super(value, successors, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.lowKey = lowKey;
     }
@@ -80,7 +80,7 @@
         int l = numberOfCases();
         for (int i = 0; i < l; i++) {
             INSTRUCTION.advance(out);
-            out.printf("case %5d: B%d%n", lowKey() + i, blockSuccessors().get(i));
+            out.printf("case %5d: B%d%n", lowKey() + i, blockSuccessor(i));
         }
         INSTRUCTION.advance(out);
         out.print("default   : ").print(defaultSuccessor());
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/TypeCheck.java	Thu Jun 16 20:43:51 2011 +0200
@@ -76,7 +76,6 @@
      * @param targetClass the class which is being casted to or checked against
      * @param object the instruction which produces the object
      * @param kind the result type of this instruction
-     * @param stateBefore the state before this instruction is executed
      * @param inputCount
      * @param successorCount
      * @param graph
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Unwind.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Unwind.java	Thu Jun 16 20:43:51 2011 +0200
@@ -29,7 +29,7 @@
 /**
  * Unwind takes an exception object, destroys the current stack frame and passes the exception object to the system's exception dispatch code.
  */
-public final class Unwind extends BlockEnd {
+public final class Unwind extends FixedNode {
 
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_EXCEPTION = 0;
@@ -46,11 +46,6 @@
         return super.successorCount() + SUCCESSOR_COUNT;
     }
 
-    @Override
-    public Instruction next() {
-        return null;
-    }
-
     /**
      * The instruction that produces the exception object.
      */
@@ -64,7 +59,7 @@
     }
 
     public Unwind(Value exception, Graph graph) {
-        super(CiKind.Object, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        super(CiKind.Object, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setException(exception);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Thu Jun 16 20:43:51 2011 +0200
@@ -51,6 +51,7 @@
     public abstract void visitLocal(Local i);
     public abstract void visitLogic(Logic i);
     public abstract void visitLookupSwitch(LookupSwitch i);
+    public abstract void visitMemoryRead(MemoryRead i);
     public abstract void visitMonitorAddress(MonitorAddress monitorAddress);
     public abstract void visitMonitorEnter(MonitorEnter i);
     public abstract void visitMonitorExit(MonitorExit i);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java	Thu Jun 16 20:43:51 2011 +0200
@@ -256,4 +256,13 @@
     public void setLastInstruction(Node n) {
         last = n;
     }
+
+    public boolean endsWithJump() {
+        List<LIRInstruction> instructionsList = lir.instructionsList();
+        if (instructionsList.size() == 0) {
+            return false;
+        }
+        LIROpcode code = instructionsList.get(instructionsList.size() - 1).code;
+        return code == LIROpcode.Branch || code == LIROpcode.TableSwitch;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBranch.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBranch.java	Thu Jun 16 20:43:51 2011 +0200
@@ -110,6 +110,7 @@
     public void changeBlock(LIRBlock b) {
         assert block != null : "must have old block";
         assert block.label() == label() : "must be equal";
+        assert b != null;
 
         this.block = b;
         this.label = b.label();
@@ -146,6 +147,7 @@
     }
 
     public void substitute(LIRBlock oldBlock, LIRBlock newBlock) {
+        assert newBlock != null;
         if (block == oldBlock) {
             block = newBlock;
             LIRInstruction instr = newBlock.lir().instructionsList().get(0);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRList.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRList.java	Thu Jun 16 20:43:51 2011 +0200
@@ -245,6 +245,7 @@
     }
 
     public void jump(LIRBlock block) {
+        assert block != null;
         append(new LIRBranch(Condition.TRUE, block));
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Thu Jun 16 20:43:51 2011 +0200
@@ -55,10 +55,11 @@
 
         iterateSuccessors();
         disconnectCFGNodes();
+        iterateInputs();
+        disconnectNodes();
+        deleteNodes();
+
         deleteBrokenLoops();
-        iterateInputs();
-        disconnectNonCFGNodes();
-        deleteNodes();
 
         new PhiSimplifier(graph);
 
@@ -68,7 +69,7 @@
     }
 
     private static boolean isCFG(Node n) {
-        return n != null && ((n instanceof Instruction) || n == n.graph().start());
+        return n != null && ((n instanceof Instruction) || (n instanceof ControlSplit) || n == n.graph().start());
     }
 
     private void iterateSuccessors() {
@@ -87,10 +88,7 @@
     private void disconnectCFGNodes() {
         for (Node node : graph.getNodes()) {
             if (node != Node.Null && !flood.isMarked(node)) {
-                if (isCFG(node)) {
-                    node.successors().clearAll();
-                    node.inputs().clearAll();
-                } else if (node instanceof EndNode) {
+                if (node instanceof EndNode) {
                     EndNode end = (EndNode) node;
                     Merge merge = end.merge();
                     if (merge != null && flood.isMarked(merge)) {
@@ -117,7 +115,7 @@
     private void deleteNodes() {
         for (Node node : graph.getNodes()) {
             if (node != Node.Null && !flood.isMarked(node)) {
-                node.delete();
+                node.unsafeDelete();
             }
         }
     }
@@ -129,25 +127,26 @@
             }
             if (node != Node.Null && flood.isMarked(node)) {
                 for (Node input : node.inputs()) {
-                    if (!isCFG(input)) {
-                        flood.add(input);
-                    }
+                    flood.add(input);
                 }
             }
         }
         for (Node current : flood) {
             for (Node input : current.inputs()) {
-                if (!isCFG(input)) {
-                    flood.add(input);
-                }
+                flood.add(input);
             }
         }
     }
 
-    private void disconnectNonCFGNodes() {
+    private void disconnectNodes() {
         for (Node node : graph.getNodes()) {
-            if (node != Node.Null && !flood.isMarked(node) && !isCFG(node)) {
-                node.inputs().clearAll();
+            if (node != Node.Null && !flood.isMarked(node)) {
+                for (int i = 0; i < node.inputs().size(); i++) {
+                    Node input = node.inputs().get(i);
+                    if (input != Node.Null && flood.isMarked(input)) {
+                        node.inputs().set(i, Node.Null);
+                    }
+                }
             }
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Thu Jun 16 20:43:51 2011 +0200
@@ -303,7 +303,7 @@
 
         int bci = target.startBci;
 
-        FrameState existingState = ((StateSplit) first).stateBefore();
+        FrameState existingState = ((StateSplit) first).stateAfter();
 
         if (existingState == null) {
             // copy state because it is modified
@@ -313,9 +313,9 @@
             if (first instanceof LoopBegin && target.isLoopHeader) {
                 assert first instanceof Merge;
                 insertLoopPhis((Merge) first, duplicate);
-                ((Merge) first).setStateBefore(duplicate);
+                ((Merge) first).setStateAfter(duplicate);
             } else {
-                ((StateSplit) first).setStateBefore(duplicate);
+                ((StateSplit) first).setStateAfter(duplicate);
             }
         } else {
             if (!GraalOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(newState)) {
@@ -328,32 +328,26 @@
             assert existingState.stackSize() == newState.stackSize();
 
             if (first instanceof Placeholder) {
+                Placeholder p = (Placeholder) first;
                 assert !target.isLoopHeader;
-                Merge merge = new Merge(graph);
-
-
-
-                Placeholder p = (Placeholder) first;
-                assert p.predecessors().size() == 1;
-                assert p.next() == null;
-
-                EndNode end = new EndNode(graph);
-                p.replace(end);
-                merge.addEnd(end);
-                //end.setNext(merge);
-                target.firstInstruction = merge;
-                merge.setStateBefore(existingState);
-                first = merge;
+                if (p.predecessors().size() == 0) {
+                    p.setStateAfter(newState.duplicate(bci));
+                    return;
+                } else {
+                    Merge merge = new Merge(graph);
+                    assert p.predecessors().size() == 1 : "predecessors size: " + p.predecessors().size();
+                    assert p.next() == null;
+                    EndNode end = new EndNode(graph);
+                    p.replace(end);
+                    merge.addEnd(end);
+                    target.firstInstruction = merge;
+                    merge.setStateAfter(existingState);
+                    first = merge;
+                }
             }
 
             existingState.merge((Merge) first, newState);
         }
-
-        for (int j = 0; j < frameState.localsSize() + frameState.stackSize(); ++j) {
-            if (frameState.valueAt(j) != null) {
-                assert !frameState.valueAt(j).isDeleted();
-            }
-        }
     }
 
     private void insertLoopPhis(Merge merge, FrameState newState) {
@@ -444,7 +438,7 @@
             FrameState entryState = frameState.duplicateWithEmptyStack(bci);
 
             StateSplit entry = new Placeholder(graph);
-            entry.setStateBefore(entryState);
+            entry.setStateAfter(entryState);
 
             Instruction currentNext = entry;
             Value currentExceptionObject = exceptionObject;
@@ -1028,7 +1022,7 @@
 
         if (needsCheck) {
             // append a call to the finalizer registration
-            append(new RegisterFinalizer(frameState.loadLocal(0), frameState.create(bci()), graph));
+            append(new RegisterFinalizer(frameState.loadLocal(0), graph));
             GraalMetrics.InlinedFinalizerChecks++;
         }
     }
@@ -1130,6 +1124,12 @@
         return append(new Constant(constant, graph));
     }
 
+    private Value append(FixedNode fixed) {
+        lastInstr.setNext(fixed);
+        lastInstr = null;
+        return fixed;
+    }
+
     private Value append(Instruction x) {
         return appendWithBCI(x);
     }
@@ -1218,7 +1218,7 @@
             if (!isVisited(block)) {
                 markVisited(block);
                 // now parse the block
-                frameState.initializeFrom(((StateSplit) block.firstInstruction).stateBefore());
+                frameState.initializeFrom(((StateSplit) block.firstInstruction).stateAfter());
                 lastInstr = block.firstInstruction;
                 assert block.firstInstruction.next() == null : "instructions already appended at block " + block.blockID;
 
@@ -1247,13 +1247,16 @@
 //                    } catch (UnresolvedException iioe) {
 //                    }
 //                }
-                if (end.stateBefore() != null) {
-                    begin.stateBefore().merge(begin, end.stateBefore());
+                if (end.stateAfter() != null) {
+                    begin.stateAfter().merge(begin, end.stateAfter());
                 } else {
                     end.delete();
                     Merge merge = new Merge(graph);
+                    for (int i = 0; i < begin.endCount(); ++i) {
+                        merge.addEnd(begin.endAt(i));
+                    }
                     merge.setNext(begin.next());
-                    begin.setNext(null);
+                    merge.setStateAfter(begin.stateAfter());
                     begin.replace(merge);
                 }
             }
@@ -1261,9 +1264,6 @@
     }
 
     private void createDeoptBlock(DeoptBlock block) {
-//        Merge x = new Merge(graph);
-//        x.setStateBefore(((StateSplit) block.firstInstruction).stateBefore());
-//        append(x);
         storeResultGraph = false;
         append(new Deoptimize(DeoptAction.InvalidateReprofile, graph));
     }
@@ -1316,8 +1316,10 @@
     }
 
     private void appendGoto(FixedNode target) {
+        if (lastInstr != null) {
         lastInstr.setNext(target);
     }
+    }
 
     private void iterateBytecodesForBlock(Block block) {
         assert frameState != null;
@@ -1325,7 +1327,6 @@
         stream.setBCI(block.startBci);
 
         int endBCI = stream.endBCI();
-        boolean blockStart = true;
 
         int bci = block.startBci;
         while (bci < endBCI) {
@@ -1338,12 +1339,11 @@
             }
             // read the opcode
             int opcode = stream.currentBC();
-
             traceState();
-            traceInstruction(bci, opcode, blockStart);
+            traceInstruction(bci, opcode, bci == block.startBci);
             processBytecode(bci, opcode);
 
-            if (IdentifyBlocksPhase.isBlockEnd(lastInstr) || lastInstr.next() != null) {
+            if (lastInstr == null || IdentifyBlocksPhase.isBlockEnd(lastInstr) || lastInstr.next() != null) {
                 break;
             }
 
@@ -1355,7 +1355,6 @@
                     stateSplit.setStateAfter(frameState.create(bci));
                 }
             }
-            blockStart = false;
         }
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Thu Jun 16 20:43:51 2011 +0200
@@ -301,7 +301,7 @@
             clipNode.setNode(new IsNonNull(parameters[0], compilation.graph));
             pred = clipNode;
         } else {
-            pred = new Placeholder(compilation.graph); // (Instruction) invoke.predecessors().get(0);//new Merge(compilation.graph);
+            pred = new Placeholder(compilation.graph);
         }
         invoke.predecessors().get(0).successors().replace(invoke, pred);
         replacements.put(startNode, pred);
@@ -340,8 +340,9 @@
             }
             Node returnDuplicate = duplicates.get(returnNode);
             returnDuplicate.inputs().clearAll();
-            returnDuplicate.replace(invoke.next());
+            Node n = invoke.next();
             invoke.setNext(null);
+            returnDuplicate.replace(n);
         }
 
         if (exceptionEdge != null) {
@@ -356,7 +357,9 @@
                     usage.inputs().replace(obj, unwindDuplicate.exception());
                 }
                 unwindDuplicate.inputs().clearAll();
-                unwindDuplicate.replace(obj.next());
+                Node n = obj.next();
+                obj.setNext(null);
+                unwindDuplicate.replace(n);
             }
         }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Thu Jun 16 20:43:51 2011 +0200
@@ -96,7 +96,7 @@
                         IntegerAdd add = (IntegerAdd) backEdge;
                         int addUsageCount = 0;
                         for (Node u : add.usages()) {
-                            if (u != loopEnd.stateBefore() && u != phi) {
+                            if (u != loopEnd.stateAfter() && u != phi) {
                                 addUsageCount++;
                             }
                         }
@@ -114,7 +114,7 @@
                         LoopCounter counter = new LoopCounter(init.kind, init, stride, loopBegin, graph);
                         counters.add(counter);
                         phi.replace(counter);
-                        loopEnd.stateBefore().inputs().replace(backEdge, counter);
+                        loopEnd.stateAfter().inputs().replace(backEdge, counter);
                         if (useCounterAfterAdd) {
                             /*IntegerAdd otherInit = new IntegerAdd(init.kind, init, stride, graph); // would be nice to canonicalize
                             LoopCounter otherCounter = new LoopCounter(init.kind, otherInit, stride, loopBegin, graph);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Thu Jun 16 20:43:51 2011 +0200
@@ -41,7 +41,7 @@
     }
 
     public final void apply(Graph graph) {
-        assert graph != null;
+        assert graph != null && graph.verify();
 
         int startDeletedNodeCount = graph.getDeletedNodeCount();
         int startNodeCount = graph.getNodeCount();
@@ -74,6 +74,8 @@
             compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + getName(), graph, true, false));
         }
 
+        assert graph.verify();
+
         // (Item|Graph|Phase|Value)
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Thu Jun 16 20:43:51 2011 +0200
@@ -65,39 +65,6 @@
         return b;
     }
 
-    private Block assignBlock(Node n) {
-        Block curBlock = nodeToBlock.get(n);
-        if (curBlock == null) {
-            curBlock = createBlock();
-            return assignBlock(n, curBlock);
-        }
-        return curBlock;
-    }
-
-
-    private Block assignBlock(Node n, Block b) {
-        assert nodeToBlock.get(n) == null;
-        nodeToBlock.set(n, b);
-        for (Node input : n.inputs()) {
-            if (input instanceof FrameState) {
-                assert nodeToBlock.get(n) == null;
-                nodeToBlock.set(n, b);
-            }
-        }
-
-        if (b.firstNode() == null) {
-            b.setFirstNode(n);
-            b.setLastNode(n);
-        } else {
-            if (b.lastNode() != null) {
-                b.getInstructions().add(b.lastNode());
-            }
-            b.setLastNode(n);
-        }
-        b.setLastNode(n);
-        return b;
-    }
-
     private Block assignBlockNew(Node n, Block b) {
         if (b == null) {
             b = createBlock();
@@ -123,7 +90,7 @@
     }
 
     public static boolean isBlockEnd(Node n) {
-        return trueSuccessorCount(n) > 1 || n instanceof Anchor || n instanceof Return || n instanceof Unwind;
+        return trueSuccessorCount(n) > 1 || n instanceof Return || n instanceof Unwind || n instanceof Deoptimize;
     }
 
     private void identifyBlocks() {
@@ -133,18 +100,19 @@
             if (n != null) {
                 if (n instanceof EndNode || n instanceof Return || n instanceof Unwind || n instanceof LoopEnd || n instanceof Deoptimize) {
                     Block block = null;
-                    while (nodeToBlock.get(n) == null) {
-                        if (block != null && IdentifyBlocksPhase.trueSuccessorCount(n) > 1) {
+                    Node currentNode = n;
+                    while (nodeToBlock.get(currentNode) == null) {
+                        if (block != null && IdentifyBlocksPhase.trueSuccessorCount(currentNode) > 1) {
                             // We are at a split node => start a new block.
                             block = null;
                         }
-                        block = assignBlockNew(n, block);
-                        if (n.predecessors().size() == 0) {
+                        block = assignBlockNew(currentNode, block);
+                        if (currentNode.predecessors().size() == 0) {
                             // Either dead code or at a merge node => stop iteration.
                             break;
                         }
-                        assert n.predecessors().size() == 1 : "preds: " + n;
-                        n = n.predecessors().get(0);
+                        assert currentNode.predecessors().size() == 1 : "preds: " + currentNode;
+                        currentNode = currentNode.predecessors().get(0);
                     }
                 }
             }
@@ -154,11 +122,6 @@
         for (Block block : blocks) {
             Node n = block.firstNode();
             if (n instanceof Merge) {
-                for (Node usage : n.usages()) {
-                    if (usage instanceof Phi || usage instanceof LoopCounter) {
-                        nodeToBlock.set(usage, block);
-                    }
-                }
                 Merge m = (Merge) n;
                 for (int i = 0; i < m.endCount(); ++i) {
                     EndNode end = m.endAt(i);
@@ -175,20 +138,6 @@
             }
         }
 
-        for (Node n : graph.getNodes()) {
-            if (n instanceof FrameState) {
-                FrameState f = (FrameState) n;
-                if (f.predecessors().size() == 1) {
-                    Block predBlock = nodeToBlock.get(f.predecessors().get(0));
-                    assert predBlock != null;
-                    nodeToBlock.set(f, predBlock);
-                    predBlock.getInstructions().add(f);
-                } else {
-                    assert f.predecessors().size() == 0;
-                }
-            }
-        }
-
         computeDominators();
 
 
@@ -277,11 +226,23 @@
             return null;
         }
 
+        assert !n.isDeleted();
+
         Block prevBlock = nodeToBlock.get(n);
         if (prevBlock != null) {
             return prevBlock;
         }
 
+        if (n instanceof Phi) {
+            Block block = nodeToBlock.get(((Phi) n).merge());
+            nodeToBlock.set(n, block);
+        }
+
+        if (n instanceof LoopCounter) {
+            Block block = nodeToBlock.get(((LoopCounter) n).loopBegin());
+            nodeToBlock.set(n, block);
+        }
+
         Block block = null;
         for (Node succ : n.successors()) {
             block = getCommonDominator(block, assignLatestPossibleBlockToNode(succ));
@@ -347,27 +308,24 @@
 
     private void sortNodesWithinBlocks(Block b, NodeBitMap map) {
         List<Node> instructions = b.getInstructions();
-        List<Node> sortedInstructions = new ArrayList<Node>();
-        assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b;
-
-        boolean scheduleFirst = true;
-        assert !instructions.contains(b.lastNode());
-        assert !instructions.contains(b.firstNode());
+        List<Node> sortedInstructions = new ArrayList<Node>(instructions.size() + 2);
 
-        if (b.firstNode() == b.lastNode()) {
-            Node node = b.firstNode();
-            if (!(node instanceof Merge) || node instanceof LoopEnd) {
-                scheduleFirst = false;
-            }
-        }
-        if (scheduleFirst) {
-            addToSorting(b, b.firstNode(), sortedInstructions, map);
-        }
+        assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b;
+        assert !instructions.contains(b.firstNode());
+        assert !instructions.contains(b.lastNode());
+        assert !map.isMarked(b.lastNode()) && nodeToBlock.get(b.lastNode()) == b;
+
+        addToSorting(b, b.firstNode(), sortedInstructions, map);
         for (Node i : instructions) {
             addToSorting(b, i, sortedInstructions, map);
         }
         addToSorting(b, b.lastNode(), sortedInstructions, map);
-        assert sortedInstructions.get(sortedInstructions.size() - 1) == b.lastNode() : "lastNode=" + b.lastNode() + ", firstNode=" + b.firstNode() + ", sorted(sz-1)=" + sortedInstructions.get(sortedInstructions.size() - 1);
+
+        // Make sure that last node gets really last (i.e. when a frame state successor hangs off it).
+        sortedInstructions.remove(b.lastNode());
+        sortedInstructions.add(b.lastNode());
+
+        assert sortedInstructions.get(sortedInstructions.size() - 1) == b.lastNode() : " lastNode=" + b.lastNode() + ", firstNode=" + b.firstNode() + ", sorted(sz-1)=" + sortedInstructions.get(sortedInstructions.size() - 1);
         b.setInstructions(sortedInstructions);
     }
 
@@ -378,11 +336,11 @@
 
         FrameState state = null;
         for (Node input : i.inputs()) {
-//            if (input instanceof FrameState) {
-//               state = (FrameState) input;
-//            } else {
+            if (input instanceof FrameState) {
+                state = (FrameState) input;
+            } else {
                 addToSorting(b, input, sortedInstructions, map);
-//            }
+            }
         }
 
         for (Node pred : i.predecessors()) {
@@ -391,16 +349,16 @@
 
         map.mark(i);
 
-        if (state != null) {
-            addToSorting(b, state, sortedInstructions, map);
-        }
-
         for (Node succ : i.successors()) {
             if (succ instanceof FrameState) {
                 addToSorting(b, succ, sortedInstructions, map);
             }
         }
 
+        if (state != null) {
+            addToSorting(b, state, sortedInstructions, map);
+        }
+
         // Now predecessors and inputs are scheduled => we can add this node.
         if (!(i instanceof FrameState)) {
             sortedInstructions.add(i);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Thu Jun 16 20:43:51 2011 +0200
@@ -398,9 +398,9 @@
     }
 
     public Merge block() {
-        for (Node usage : usages()) {
-            if (usage instanceof Merge) {
-                return (Merge) usage;
+        for (Node n : usages()) {
+            if (n instanceof Merge) {
+                return (Merge) n;
             }
         }
         return null;
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java	Thu Jun 16 20:43:51 2011 +0200
@@ -33,6 +33,8 @@
 
 public class Graph {
 
+    public static final List<VerificationListener> verificationListeners = new ArrayList<VerificationListener>(4);
+
     private final ArrayList<Node> nodes;
     private final StartNode start;
     int nextId;
@@ -149,6 +151,13 @@
         return new NodeWorkList(this, fill, iterationLimitPerNode);
     }
 
+    public boolean verify() {
+        for (Node n : getNodes()) {
+            assert n == Node.Null || n.verify();
+        }
+        return true;
+    }
+
     public Map<Node, Node> addDuplicate(Collection<Node> nodes, Map<Node, Node> replacements) {
         Map<Node, Node> newNodes = new HashMap<Node, Node>();
         // create node duplicates
@@ -184,7 +193,7 @@
                 }
             }
         }
-        
+
         // re-wire successors
         for (Entry<Node, Node> entry : newNodes.entrySet()) {
             Node oldNode = entry.getKey();
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Thu Jun 16 20:43:51 2011 +0200
@@ -104,6 +104,7 @@
         usages.clear();
         predecessors.clear();
         delete();
+        assert other == null || other.verify();
         return other;
     }
 
@@ -122,9 +123,15 @@
         predecessors.clear();
     }
 
+    public void unsafeDelete() {
+        graph.unregister(this);
+        id = DeletedID;
+        assert isDeleted();
+    }
+
     public void delete() {
         assert !isDeleted();
-        assert checkDeletion() : "Could not delete " + this;
+        assert checkDeletion() : "Could not delete " + this + " (usages: " + this.usages() + ", predecessors: " + this.predecessors() + ")";
 
         for (int i = 0; i < inputs.size(); ++i) {
             inputs.set(i, Null);
@@ -133,10 +140,7 @@
             successors.set(i, Null);
         }
         assert predecessors().size() == 0 && usages().size() == 0;
-        // make sure its not connected. pred usages
-        graph.unregister(this);
-        id = DeletedID;
-        assert isDeleted();
+        unsafeDelete();
     }
 
     private boolean checkDeletion() {
@@ -200,4 +204,19 @@
     public String toString() {
         return this.getClass().getSimpleName() + "-" + this.id();
     }
+
+    public boolean verify() {
+        return true;
+    }
+
+    public final void assertTrue(boolean cond) {
+        assert cond || assertionFailure();
+    }
+
+    public final boolean assertionFailure() {
+        for (VerificationListener l : Graph.verificationListeners) {
+            l.verificationFailed(this);
+        }
+        return true;
+    }
 }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java	Thu Jun 16 20:36:17 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java	Thu Jun 16 20:43:51 2011 +0200
@@ -53,7 +53,7 @@
         nodes[index] = node;
         return result;
     }
-    
+
     public AbstractList<Node> variablePart() {
         return new AbstractList<Node>() {
 
@@ -77,24 +77,24 @@
                 variableLength++;
                 checkIndex(index);
                 NodeArray.this.ensureSize();
-                for (int i=size() - 1; i > index; i--) {
-                    NodeArray.this.nodes[fixedLength + i] = NodeArray.this.nodes[fixedLength + i-1];
+                for (int i = size() - 1; i > index; i--) {
+                    NodeArray.this.nodes[fixedLength + i] = NodeArray.this.nodes[fixedLength + i - 1];
                 }
                 set(index, element);
             }
-            
+
             private void checkIndex(int index) {
                 if (index < 0 || index >= size()) {
                     throw new IndexOutOfBoundsException();
                 }
             }
-            
+
             @Override
             public Node remove(int index) {
                 checkIndex(index);
                 Node n = get(index);
                 set(index, Node.Null);
-                for (int i=index; i < size() - 1; i++) {
+                for (int i = index; i < size() - 1; i++) {
                     NodeArray.this.nodes[fixedLength + i] = NodeArray.this.nodes[fixedLength + i + 1];
                 }
                 NodeArray.this.nodes[fixedLength + size() - 1] = Node.Null;
@@ -107,19 +107,19 @@
 
     private void ensureSize() {
         if (size() > nodes.length) {
-            nodes = Arrays.copyOf(nodes, (nodes.length + 1)*2);
+            nodes = Arrays.copyOf(nodes, (nodes.length + 1) * 2);
         }
     }
-    
+
     public void setOrExpand(int index, Node node) {
         if (index < 0) {
             throw new IndexOutOfBoundsException();
         }
-        
+
         while (index >= size()) {
             variablePart().add(Node.Null);
         }
-        
+
         set(index, node);
     }
 
@@ -129,7 +129,7 @@
         assert node == Node.Null || node.graph == self().graph : "node is from different graph: (this=" + self() + ") and (node=" + node + ")";
         assert node == Node.Null || node.id() != Node.DeletedID : "inserted node must not be deleted";
         assert node != self() || node.getClass().toString().contains("Phi") : "No direct circles allowed in the graph! " + node;
-        
+
         Node old = get(index);
         if (old != node) {
             silentSet(index, node);
@@ -143,13 +143,7 @@
             } else {
                 assert self().successors == this;
                 if (old != null) {
-                    for (int i = 0; i < old.predecessors.size(); ++i) {
-                        Node cur = old.predecessors.get(i);
-                        if (cur == self()) {
-                            old.predecessors.remove(i);
-                            break;
-                        }
-                    }
+                    old.predecessors.remove(self());
                 }
                 if (node != null) {
                     node.predecessors.add(self());
@@ -166,7 +160,7 @@
             set(i, other.get(i));
         }
     }
-    
+
     private void checkIndex(int index) {
         if (index < 0 || index >= size()) {
             throw new IndexOutOfBoundsException();
@@ -176,6 +170,7 @@
     @Override
     public Node get(int index) {
         checkIndex(index);
+        assert !self().isDeleted();
         return nodes[index];
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/VerificationListener.java	Thu Jun 16 20:43:51 2011 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.graph;
+
+
+public interface VerificationListener {
+    void verificationFailed(Node n);
+}