changeset 4309:4a609a685fa4

changes to Node structures: * add more uses of higher-level graph manipulation methods * CanonicalierPhase cleanup * introduce FloatingReadNode, make ReadNode an ordinary fixed nodeToBlock * let Canonicalizable.canonical return ValueNode (instead of Node)
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 17 Jan 2012 19:45:39 +0100
parents cbed6f7e2d10
children 72d099e5be61
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/BoxingEliminationPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RemovePlaceholderPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/AnchorNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/BeginNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FixedGuardNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/GuardNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/IfNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/PhiNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/StructuredGraph.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/AndNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/CompareNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/ConditionalNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/ConvertNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatAddNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatDivNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatMulNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatRemNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatSubNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerAddNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerDivNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerMulNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerRemNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerSubNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/LeftShiftNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/NegateNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/NullCheckNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/OrNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/RightShiftNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/UnsignedRightShiftNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/XorNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/Access.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/AccessNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/FloatingAccessNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/FloatingReadNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/IndexedLocationNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/ReadNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/SafeReadNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/UnboxNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/UnsafeCastNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/UnsafeLoadNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/ValueAnchorNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/ArrayLengthNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/IsTypeNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/LoadFieldNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/MethodCallTargetNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/NewArrayNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/NewInstanceNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/RegisterFinalizerNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/loop/BasicInductionVariableNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/loop/DerivedInductionVariableNode.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/Canonicalizable.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/EscapeOp.java graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/util/GraphUtil.java graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/nodes/MathIntrinsicNode.java graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/FloatingReadTest.java
diffstat 71 files changed, 362 insertions(+), 247 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Tue Jan 17 19:45:39 2012 +0100
@@ -359,11 +359,11 @@
                     GuardNode guardNode = (GuardNode) instr;
                     if (guardNode.condition() instanceof NullCheckNode) {
                         NullCheckNode nullCheckNode = (NullCheckNode) guardNode.condition();
-                        if (!nullCheckNode.expectedNull && nextInstr instanceof AccessNode) {
-                            AccessNode accessNode = (AccessNode) nextInstr;
-                            if (nullCheckNode.object() == accessNode.object() && canBeNullCheck(accessNode.location())) {
+                        if (!nullCheckNode.expectedNull && nextInstr instanceof Access) {
+                            Access access = (Access) nextInstr;
+                            if (nullCheckNode.object() == access.object() && canBeNullCheck(access.location())) {
                                 //TTY.println("implicit null check");
-                                accessNode.setNullCheck(true);
+                                access.setNullCheck(true);
                                 continue;
                             }
                         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/BoxingEliminationPhase.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/BoxingEliminationPhase.java	Tue Jan 17 19:45:39 2012 +0100
@@ -66,7 +66,8 @@
             if (phiNode.stamp().nonNull()) {
                 RiResolvedType exactType = phiNode.stamp().exactType();
                 if (exactType != null && exactType.toJava() == kind.toUnboxedJavaClass()) {
-                    result = phiNode.graph().add(new PhiNode(kind, phiNode.merge(), PhiType.Value));
+                    StructuredGraph graph = (StructuredGraph) phiNode.graph();
+                    result = graph.add(new PhiNode(kind, phiNode.merge(), PhiType.Value));
                     phiReplacements.put(phiNode, result);
                     virtualizeUsages(phiNode, result, exactType);
                     int i = 0;
@@ -76,10 +77,9 @@
                             assert unboxedValue.kind() == kind;
                             result.addInput(unboxedValue);
                         } else {
-                            UnboxNode unboxNode = phiNode.graph().add(new UnboxNode(kind, n));
+                            UnboxNode unboxNode = graph.add(new UnboxNode(kind, n));
                             FixedNode pred = phiNode.merge().phiPredecessorAt(i);
-                            pred.replaceAtPredecessors(unboxNode);
-                            unboxNode.setNext(pred);
+                            graph.addBeforeFixed(pred, unboxNode);
                             result.addInput(unboxNode);
                         }
                         ++i;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java	Tue Jan 17 19:45:39 2012 +0100
@@ -26,10 +26,10 @@
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.calc.*;
-import com.oracle.max.graal.nodes.extended.*;
 import com.oracle.max.graal.nodes.spi.*;
 
 public class CanonicalizerPhase extends Phase {
@@ -69,48 +69,55 @@
                     TTY.println("Canonicalizer: work on " + node);
                 }
                 graph.mark();
-                Node canonical = ((Canonicalizable) node).canonical(tool);
-                if (canonical == null) {
-                    node.safeDelete();
-                } else if (canonical != node) {
+                ValueNode canonical = ((Canonicalizable) node).canonical(tool);
 //     cases:                                           original node:
 //                                         |Floating|Fixed-unconnected|Fixed-connected|
 //                                         --------------------------------------------
-//                                     null|   1    |        X        |       3       |
+//                                     null|   1    |        X        |       1       |
 //                                         --------------------------------------------
-//                                 Floating|   1    |        X        |       3       |
+//                                 Floating|   2    |        X        |       4       |
 //       canonical node:                   --------------------------------------------
-//                        Fixed-unconnected|   X    |        X        |       2       |
+//                        Fixed-unconnected|   X    |        X        |       3       |
 //                                         --------------------------------------------
-//                          Fixed-connected|   1    |        X        |       3       |
+//                          Fixed-connected|   2    |        X        |       4       |
 //                                         --------------------------------------------
 //       X: must not happen (checked with assertions)
-                    if (node instanceof FloatingNode) {
-                        // case 1
-                        assert canonical == null || canonical instanceof FloatingNode || (canonical instanceof FixedNode && canonical.predecessor() != null) || canonical instanceof ReadNode : canonical;
-                        node.replaceAndDelete(canonical);
+                if (canonical == null) {
+                    // case 1
+                    node.replaceAtUsages(null);
+                    if (Util.isFixed(node)) {
+                        graph.removeFixed((FixedWithNextNode) node);
                     } else {
-                        assert node instanceof FixedNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
-                        if (canonical instanceof FixedNode && canonical.predecessor() == null) {
-                            // case 2
-                            node.replaceAndDelete(canonical);
+                        graph.removeFloating((FloatingNode) node);
+                    }
+                } else if (canonical != node) {
+                    if (node instanceof FloatingNode) {
+                        // case 2
+                        assert Util.isFloating(canonical) || (Util.isFixed(canonical) && canonical.predecessor() != null) : canonical;
+                        graph.replaceFloating((FloatingNode) node, canonical);
+                    } else {
+                        assert Util.isFixed(node) && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
+                        if (Util.isFixed(canonical) && canonical.predecessor() == null) {
+                            // case 3
+                            graph.replaceFixedWithFixed((FixedWithNextNode) node, (FixedWithNextNode) canonical);
                         } else {
-                            // case 3
-                            FixedNode nextNode = null;
+                            // case 4
+                            node.replaceAtUsages(canonical);
                             if (node instanceof FixedWithNextNode) {
-                                nextNode = ((FixedWithNextNode) node).next();
+                                graph.removeFixed((FixedWithNextNode) node);
                             } else if (node instanceof ControlSplitNode) {
-                                for (FixedNode sux : ((ControlSplitNode) node).blockSuccessors()) {
-                                    if (nextNode == null) {
-                                        nextNode = sux;
+                                // FIX(ls) is this logic really used? the semantics might be hard to understand...
+                                ControlSplitNode split = (ControlSplitNode) node;
+                                int survivingSuccessor = -1;
+                                for (int i = 0; i < split.blockSuccessorCount(); i++) {
+                                    if (survivingSuccessor == -1 && split.blockSuccessor(i) != null) {
+                                        survivingSuccessor = i;
                                     } else {
-                                        assert sux == null;
+                                        assert split.blockSuccessor(i) == null;
                                     }
                                 }
+                                graph.removeSplit(split, survivingSuccessor);
                             }
-                            node.clearSuccessors();
-                            node.replaceAtPredecessors(nextNode);
-                            node.replaceAndDelete(canonical);
                         }
                     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Tue Jan 17 19:45:39 2012 +0100
@@ -101,7 +101,7 @@
 
     private static void replacePhis(MergeNode merge) {
         for (PhiNode phi : merge.phis().snapshot()) {
-            phi.replaceAndDelete((phi).valueAt(0));
+            ((StructuredGraph) merge.graph()).replaceFloating(phi, phi.valueAt(0));
         }
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java	Tue Jan 17 19:45:39 2012 +0100
@@ -223,7 +223,7 @@
 
         public void apply() {
             if (node.usages().isEmpty()) {
-                node.replaceAndDelete(node.next());
+                graph.removeFixed(node);
             } else {
                 process();
                 removeAllocation();
@@ -240,8 +240,8 @@
                 TTY.println("new virtual object: " + virtual);
             }
             node.replaceAtUsages(virtual);
-            final FixedNode next = node.next();
-            node.replaceAndDelete(next);
+            FixedNode next = node.next();
+            graph.removeFixed(node);
 
             if (virtual.fieldsCount() > 0) {
                 final BlockExitState startState = new BlockExitState(escapeFields, virtual);
@@ -486,7 +486,7 @@
                 }
             }
             if (!required) {
-                phi.replaceAndDelete(simpleValue);
+                ((StructuredGraph) node.graph()).replaceFloating(phi, simpleValue);
             }
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java	Tue Jan 17 19:45:39 2012 +0100
@@ -152,18 +152,20 @@
         }
 
         public void processRead(ReadNode readNode) {
-            FixedNode next = readNode.next();
-            readNode.setNext(null);
-            readNode.replaceAtPredecessors(next);
+            StructuredGraph graph = (StructuredGraph) readNode.graph();
+            assert readNode.getNullCheck() == false;
 
             if (GraalOptions.TraceMemoryMaps) {
                 TTY.println("Register read to node " + readNode);
             }
 
-            if (readNode.location().locationIdentity() != LocationNode.FINAL_LOCATION) {
-                // Create dependency on previous node that creates the memory state for this location.
-                readNode.addDependency(getLocationForRead(readNode));
+            FloatingReadNode floatingRead;
+            if (readNode.location().locationIdentity() == LocationNode.FINAL_LOCATION) {
+                floatingRead = graph.unique(new FloatingReadNode(readNode.kind(), readNode.object(), readNode.guard(), readNode.location()));
+            } else {
+                floatingRead = graph.unique(new FloatingReadNode(readNode.kind(), readNode.object(), readNode.guard(), readNode.location(), getLocationForRead(readNode)));
             }
+            graph.replaceFixedWithFloating(readNode, floatingRead);
         }
 
         private Node getLocationForRead(ReadNode readNode) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ReadEliminationPhase.java	Tue Jan 17 19:45:39 2012 +0100
@@ -32,8 +32,9 @@
 
     @Override
     protected void run(StructuredGraph graph) {
-        for (ReadNode n : graph.getNodes(ReadNode.class)) {
+        for (FloatingReadNode n : graph.getNodes(FloatingReadNode.class)) {
             if (n.dependencies().size() > 0) {
+                assert n.dependencies().size() == 1;
                 Node memoryInput = n.dependencies().get(0);
                 if (memoryInput instanceof WriteNode) {
                     WriteNode other = (WriteNode) memoryInput;
@@ -41,7 +42,7 @@
                         if (GraalOptions.TraceReadElimination) {
                             TTY.println("Eliminated memory read " + n + "and replaced with node " + other.value());
                         }
-                        n.replaceAndDelete(other.value());
+                        graph.replaceFloating(n, other.value());
                     }
                 }
             }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RemovePlaceholderPhase.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RemovePlaceholderPhase.java	Tue Jan 17 19:45:39 2012 +0100
@@ -28,7 +28,7 @@
     @Override
     protected void run(StructuredGraph graph) {
         for (PlaceholderNode n : graph.getNodes(PlaceholderNode.class)) {
-            n.replaceAndDelete(n.next());
+            graph.removeFixed(n);
         }
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java	Tue Jan 17 19:45:39 2012 +0100
@@ -162,24 +162,28 @@
 
     public void cleanUpReturnCheckCast(Node newInstance) {
         if (newInstance instanceof ValueNode && ((ValueNode) newInstance).kind() != CiKind.Object) {
+            StructuredGraph graph = (StructuredGraph) newInstance.graph();
             for (Node usage : newInstance.usages().snapshot()) {
                 if (usage instanceof CheckCastNode) {
                     CheckCastNode checkCastNode = (CheckCastNode) usage;
                     for (Node checkCastUsage : checkCastNode.usages().snapshot()) {
                         if (checkCastUsage instanceof ValueAnchorNode) {
                             ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage;
-                            valueAnchorNode.replaceAndDelete(valueAnchorNode.next());
+                            graph.removeFixed(valueAnchorNode);
                         } else if (checkCastUsage instanceof MethodCallTargetNode) {
                             MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage;
                             assert pool.isUnboxingMethod(checkCastCallTarget.targetMethod());
                             Invoke invokeNode = checkCastCallTarget.invoke();
+                            invokeNode.node().replaceAtUsages(newInstance);
                             if (invokeNode instanceof InvokeWithExceptionNode) {
                                 // Destroy exception edge & clear stateAfter.
                                 InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode;
+
                                 invokeWithExceptionNode.killExceptionEdge();
+                                graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE);
+                            } else {
+                                graph.removeFixed((InvokeNode) invokeNode);
                             }
-                            invokeNode.node().replaceAtUsages(newInstance);
-                            invokeNode.node().replaceAndDelete(invokeNode.next());
                             checkCastCallTarget.safeDelete();
                         } else if (checkCastUsage instanceof FrameState) {
                             checkCastUsage.replaceFirstInput(checkCastNode, null);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Tue Jan 17 19:45:39 2012 +0100
@@ -28,6 +28,7 @@
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.graph.Node.Verbosity;
 import com.oracle.max.graal.nodes.*;
@@ -206,10 +207,6 @@
         return b;
     }
 
-    public static boolean isFixed(Node n) {
-        return n != null && n instanceof FixedNode && !(n instanceof AccessNode && n.predecessor() == null);
-    }
-
     public static boolean isBlockEnd(Node n) {
         return trueSuccessorCount(n) > 1 || n instanceof ReturnNode || n instanceof UnwindNode || n instanceof DeoptimizeNode;
     }
@@ -238,7 +235,8 @@
                     }
                     prev = currentNode;
                     currentNode = currentNode.predecessor();
-                    assert !(currentNode instanceof AccessNode && ((AccessNode) currentNode).next() != prev) : currentNode;
+                    // FIX(ls) what's the meaning of this assert?
+//                    assert !(currentNode instanceof AccessNode && ((AccessNode) currentNode).next() != prev) : currentNode;
                     assert !currentNode.isDeleted() : prev + " " + currentNode;
                 }
             }
@@ -255,7 +253,7 @@
                 }
             } else {
                 if (n.predecessor() != null) {
-                    if (isFixed(n.predecessor())) {
+                    if (Util.isFixed(n.predecessor())) {
                         Block predBlock = nodeToBlock.get(n.predecessor());
                         predBlock.addSuccessor(block);
                     }
@@ -646,7 +644,7 @@
         }
         int i = 0;
         for (Node s : n.successors()) {
-            if (isFixed(s)) {
+            if (Util.isFixed(s)) {
                 i++;
             }
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java	Tue Jan 17 19:45:39 2012 +0100
@@ -340,7 +340,7 @@
      */
     public static Node inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) {
         NodeInputList<ValueNode> parameters = invoke.callTarget().arguments();
-        Graph graph = invoke.node().graph();
+        StructuredGraph graph = (StructuredGraph) invoke.node().graph();
 
         FrameState stateAfter = invoke.stateAfter();
         assert stateAfter.isAlive();
@@ -375,16 +375,11 @@
         Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements);
 
         FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
-        FixedNode invokeReplacement;
         MethodCallTargetNode callTarget = invoke.callTarget();
-        if (callTarget.isStatic() || !receiverNullCheck || parameters.get(0).kind() != CiKind.Object || parameters.get(0).stamp().nonNull()) {
-            invokeReplacement = firstCFGNodeDuplicate;
-        } else {
-            FixedGuardNode guard = graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(parameters.get(0), false))));
-            guard.setNext(firstCFGNodeDuplicate);
-            invokeReplacement = guard;
+        if (!callTarget.isStatic() && receiverNullCheck && parameters.get(0).kind() == CiKind.Object && !parameters.get(0).stamp().nonNull()) {
+            graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new NullCheckNode(parameters.get(0), false)))));
         }
-        invoke.node().replaceAtPredecessors(invokeReplacement);
+        invoke.node().replaceAtPredecessors(firstCFGNodeDuplicate);
 
         FrameState stateAtExceptionEdge = null;
         if (invoke instanceof InvokeWithExceptionNode) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Tue Jan 17 19:45:39 2012 +0100
@@ -28,6 +28,7 @@
 import com.oracle.max.criutils.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.calc.*;
 
 /**
  * The {@code Util} class contains a motley collection of utility methods used throughout the compiler.
@@ -362,4 +363,12 @@
         }
         return false;
     }
+
+    public static boolean isFixed(Node n) {
+        return n instanceof FixedNode;
+    }
+
+    public static boolean isFloating(Node n) {
+        return n instanceof FloatingNode;
+    }
 }
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java	Tue Jan 17 19:45:39 2012 +0100
@@ -27,9 +27,10 @@
 import java.util.*;
 
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ci.CiTargetMethod.*;
+import com.oracle.max.cri.ci.CiTargetMethod.DataPatch;
+import com.oracle.max.cri.ci.CiTargetMethod.Safepoint;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.cri.ri.RiType.*;
+import com.oracle.max.cri.ri.RiType.Representation;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.cri.*;
 import com.oracle.max.graal.graph.*;
@@ -204,11 +205,11 @@
         if (!GraalOptions.Lower) {
             return;
         }
+        StructuredGraph graph = (StructuredGraph) n.graph();
 
         if (n instanceof ArrayLengthNode) {
             ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n;
             SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.graph(), arrayLengthNode.array());
-            StructuredGraph graph = (StructuredGraph) arrayLengthNode.graph();
             graph.replaceFixedWithFixed(arrayLengthNode, safeReadArrayLength);
             safeReadArrayLength.lower(tool);
         } else if (n instanceof LoadFieldNode) {
@@ -216,50 +217,38 @@
             if (field.isVolatile()) {
                 return;
             }
-            StructuredGraph graph = (StructuredGraph) field.graph();
             int displacement = ((HotSpotField) field.field()).offset();
             assert field.kind() != CiKind.Illegal;
-            ReadNode memoryRead = graph.unique(new ReadNode(field.field().kind(true).stackKind(), field.object(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph)));
+            ReadNode memoryRead = graph.add(new ReadNode(field.field().kind(true).stackKind(), field.object(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph)));
             memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false))));
             graph.replaceFixedWithFixed(field, memoryRead);
         } else if (n instanceof StoreFieldNode) {
-            StoreFieldNode field = (StoreFieldNode) n;
-            if (field.isVolatile()) {
+            StoreFieldNode storeField = (StoreFieldNode) n;
+            if (storeField.isVolatile()) {
                 return;
             }
-            Graph graph = field.graph();
-            int displacement = ((HotSpotField) field.field()).offset();
-            WriteNode memoryWrite = graph.add(new WriteNode(field.object(), field.value(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph)));
-            memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false))));
-            memoryWrite.setStateAfter(field.stateAfter());
-            FixedNode next = field.next();
-            field.setNext(null);
-            if (field.field().kind(true) == CiKind.Object && !field.value().isNullConstant()) {
-                FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(field.object()));
-                memoryWrite.setNext(writeBarrier);
-                writeBarrier.setNext(next);
-            } else {
-                memoryWrite.setNext(next);
+            HotSpotField field = (HotSpotField) storeField.field();
+            WriteNode memoryWrite = graph.add(new WriteNode(storeField.object(), storeField.value(), LocationNode.create(storeField.field(), storeField.field().kind(true), field.offset(), graph)));
+            memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(storeField.object(), false))));
+            memoryWrite.setStateAfter(storeField.stateAfter());
+            graph.replaceFixedWithFixed(storeField, memoryWrite);
+
+            if (field.kind(true) == CiKind.Object && !memoryWrite.value().isNullConstant()) {
+                graph.addAfterFixed(memoryWrite, graph.add(new FieldWriteBarrier(memoryWrite.object())));
             }
-            field.replaceAndDelete(memoryWrite);
         } else if (n instanceof LoadIndexedNode) {
             LoadIndexedNode loadIndexed = (LoadIndexedNode) n;
-            StructuredGraph graph = (StructuredGraph) loadIndexed.graph();
             GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool);
 
             CiKind elementKind = loadIndexed.elementKind();
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index());
-            ReadNode memoryRead = graph.unique(new ReadNode(elementKind.stackKind(), loadIndexed.array(), arrayLocation));
+            ReadNode memoryRead = graph.add(new ReadNode(elementKind.stackKind(), loadIndexed.array(), arrayLocation));
             memoryRead.setGuard(boundsCheck);
             graph.replaceFixedWithFixed(loadIndexed, memoryRead);
         } else if (n instanceof StoreIndexedNode) {
             StoreIndexedNode storeIndexed = (StoreIndexedNode) n;
-            Graph graph = storeIndexed.graph();
-            AnchorNode anchor = graph.add(new AnchorNode());
             GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool);
 
-            FixedWithNextNode append = anchor;
-
             CiKind elementKind = storeIndexed.elementKind();
             LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index());
             ValueNode value = storeIndexed.value();
@@ -269,48 +258,43 @@
                 if (array.exactType() != null) {
                     RiResolvedType elementType = array.exactType().componentType();
                     if (elementType.superType() != null) {
+                        AnchorNode anchor = graph.add(new AnchorNode());
+                        graph.addBeforeFixed(storeIndexed, anchor);
                         ConstantNode type = graph.unique(ConstantNode.forCiConstant(elementType.getEncoding(Representation.ObjectHub), this, graph));
                         value = graph.unique(new CheckCastNode(anchor, type, elementType, value));
                     } else {
                         assert elementType.name().equals("Ljava/lang/Object;") : elementType.name();
                     }
                 } else {
+                    AnchorNode anchor = graph.add(new AnchorNode());
+                    graph.addBeforeFixed(storeIndexed, anchor);
                     GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false)));
-                    ReadNode arrayClass = graph.unique(new ReadNode(CiKind.Object, array, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph)));
+                    ReadNode arrayClass = graph.add(new ReadNode(CiKind.Object, array, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph)));
                     arrayClass.setGuard(guard);
-                    append.setNext(arrayClass);
-                    append = arrayClass;
-                    ReadNode arrayElementKlass = graph.unique(new ReadNode(CiKind.Object, arrayClass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph)));
+                    graph.addBeforeFixed(storeIndexed, arrayClass);
+                    ReadNode arrayElementKlass = graph.add(new ReadNode(CiKind.Object, arrayClass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph)));
                     value = graph.unique(new CheckCastNode(anchor, arrayElementKlass, null, value));
                 }
             }
             WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation));
             memoryWrite.setGuard(boundsCheck);
             memoryWrite.setStateAfter(storeIndexed.stateAfter());
-            FixedNode next = storeIndexed.next();
-            storeIndexed.setNext(null);
-            append.setNext(memoryWrite);
+
+            graph.replaceFixedWithFixed(storeIndexed, memoryWrite);
+
             if (elementKind == CiKind.Object && !value.isNullConstant()) {
-                ArrayWriteBarrier writeBarrier = graph.add(new ArrayWriteBarrier(array, arrayLocation));
-                memoryWrite.setNext(writeBarrier);
-                writeBarrier.setNext(next);
-            } else {
-                memoryWrite.setNext(next);
+                graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation)));
             }
-            storeIndexed.replaceAtPredecessors(anchor);
-            storeIndexed.safeDelete();
         } else if (n instanceof UnsafeLoadNode) {
             UnsafeLoadNode load = (UnsafeLoadNode) n;
-            StructuredGraph graph = (StructuredGraph) load.graph();
             assert load.kind() != CiKind.Illegal;
             IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph);
             location.setIndexScalingEnabled(false);
-            ReadNode memoryRead = graph.unique(new ReadNode(load.kind(), load.object(), location));
+            ReadNode memoryRead = graph.add(new ReadNode(load.kind(), load.object(), location));
             memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false))));
             graph.replaceFixedWithFixed(load, memoryRead);
         } else if (n instanceof UnsafeStoreNode) {
             UnsafeStoreNode store = (UnsafeStoreNode) n;
-            StructuredGraph graph = (StructuredGraph) store.graph();
             IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.storeKind(), store.displacement(), store.offset(), graph);
             location.setIndexScalingEnabled(false);
             WriteNode write = graph.add(new WriteNode(store.object(), store.value(), location));
@@ -319,7 +303,8 @@
             graph.replaceFixedWithFixed(store, write);
             graph.addBeforeFixed(write, barrier);
         } else if (n instanceof ArrayHeaderSizeNode) {
-            n.replaceAndDelete(ConstantNode.forLong(config.getArrayOffset(((ArrayHeaderSizeNode) n).elementKind()), n.graph()));
+            ArrayHeaderSizeNode arrayHeaderSize = (ArrayHeaderSizeNode) n;
+            graph.replaceFloating(arrayHeaderSize, ConstantNode.forLong(config.getArrayOffset(arrayHeaderSize.elementKind()), n.graph()));
         }
     }
 
@@ -362,7 +347,7 @@
                 SafeReadNode klassOop = safeRead(graph, CiKind.Object, receiver, config.klassOopOffset);
                 graph.start().setNext(klassOop);
                 // TODO(tw): Care about primitive classes!
-                ReadNode result = graph.unique(new ReadNode(CiKind.Int, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Int, config.klassModifierFlagsOffset, graph)));
+                ReadNode result = graph.add(new ReadNode(CiKind.Int, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Int, config.klassModifierFlagsOffset, graph)));
                 ReturnNode ret = graph.add(new ReturnNode(result));
                 klassOop.setNext(ret);
                 return graph;
--- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java	Tue Jan 17 19:45:39 2012 +0100
@@ -183,7 +183,7 @@
 
         // remove Placeholders (except for loop exits)
         for (PlaceholderNode n : currentGraph.getNodes(PlaceholderNode.class)) {
-            n.replaceAndDelete(n.next());
+            currentGraph.removeFixed(n);
         }
 
         // remove dead FrameStates
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/AnchorNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/AnchorNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -42,7 +42,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (this.usages().size() == 0 && guards.size() == 0) {
             return next();
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/BeginNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/BeginNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -50,7 +50,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         FixedNode prev = (FixedNode) this.predecessor();
         if (prev == null) {
             // This is the start node.
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FixedGuardNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FixedGuardNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -53,7 +53,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         for (BooleanNode n : conditions.snapshot()) {
             if (n instanceof ConstantNode) {
                 ConstantNode c = (ConstantNode) n;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java	Tue Jan 17 19:45:39 2012 +0100
@@ -454,7 +454,7 @@
 
     public void deleteRedundantPhi(PhiNode redundantPhi, ValueNode phiValue) {
         Collection<PhiNode> phiUsages = redundantPhi.usages().filter(PhiNode.class).snapshot();
-        redundantPhi.replaceAndDelete(phiValue);
+        ((StructuredGraph) graph()).replaceFloating(redundantPhi, phiValue);
         for (Node n : phiUsages) {
             PhiNode phiNode = (PhiNode) n;
             checkRedundantPhi(phiNode);
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/GuardNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/GuardNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.max.graal.nodes;
 
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.calc.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
@@ -60,7 +59,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (condition() instanceof ConstantNode) {
             ConstantNode c = (ConstantNode) condition();
             if (c.asConstant().asBoolean()) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/IfNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/IfNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.max.graal.nodes;
 
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
 
@@ -100,7 +99,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (compare() instanceof ConstantNode) {
             ConstantNode c = (ConstantNode) compare();
             if (c.asConstant().asBoolean()) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/InvokeWithExceptionNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -32,8 +32,8 @@
 import com.oracle.max.graal.nodes.util.*;
 
 public class InvokeWithExceptionNode extends ControlSplitNode implements Node.IterableNodeType, Invoke, MemoryCheckpoint, LIRLowerable {
-    private static final int NORMAL_EDGE = 0;
-    private static final int EXCEPTION_EDGE = 1;
+    public static final int NORMAL_EDGE = 0;
+    public static final int EXCEPTION_EDGE = 1;
 
     @Input private final MethodCallTargetNode callTarget;
     @Input private FrameState stateAfter;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/PhiNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/PhiNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -160,7 +160,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         ValueNode singleValue = singleValue();
 
         if (singleValue != null) {
@@ -170,7 +170,7 @@
         return canonicalizeMaterializationPhi();
     }
 
-    private Node canonicalizeMaterializationPhi() {
+    private ValueNode canonicalizeMaterializationPhi() {
         if (merge().endCount() != 2 || merge() instanceof LoopBeginNode) {
             return this;
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/StructuredGraph.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/StructuredGraph.java	Tue Jan 17 19:45:39 2012 +0100
@@ -140,7 +140,16 @@
         return getNodes(LoopBeginNode.class).iterator().hasNext();
     }
 
+    public void removeFloating(FloatingNode node) {
+        assert node != null && node.isAlive() : "cannot remove " + node;
+        node.safeDelete();
+    }
 
+    public void replaceFloating(FloatingNode node, ValueNode replacement) {
+        assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement;
+        node.replaceAtUsages(replacement);
+        node.safeDelete();
+    }
 
     public void removeFixed(FixedWithNextNode node) {
         assert node != null;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/AndNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/AndNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return x();
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/CompareNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/CompareNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -24,7 +24,6 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
@@ -116,7 +115,7 @@
         }
     }
 
-    private Node optimizeMaterialize(CiConstant constant, MaterializeNode materializeNode, RiRuntime runtime) {
+    private ValueNode optimizeMaterialize(CiConstant constant, MaterializeNode materializeNode, RiRuntime runtime) {
         CiConstant trueConstant = materializeNode.trueValue().asConstant();
         CiConstant falseConstant = materializeNode.falseValue().asConstant();
 
@@ -144,7 +143,7 @@
         return this;
     }
 
-    private Node optimizeNormalizeCmp(CiConstant constant, NormalizeCompareNode normalizeNode) {
+    private ValueNode optimizeNormalizeCmp(CiConstant constant, NormalizeCompareNode normalizeNode) {
         if (constant.kind == CiKind.Int && constant.asInt() == 0) {
             Condition cond = condition();
             if (normalizeNode.x().kind().isFloatOrDouble()) {
@@ -167,7 +166,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && !y().isConstant()) { // move constants to the left (y)
             return graph().unique(new CompareNode(y(), condition.mirror(), unorderedIsTrue(), x()));
         } else if (x().isConstant() && y().isConstant()) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/ConditionalNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/ConditionalNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -90,7 +90,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (condition instanceof ConstantNode) {
             ConstantNode c = (ConstantNode) condition;
             if (c.asConstant().asBoolean()) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/ConvertNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/ConvertNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -25,7 +25,6 @@
 import static com.oracle.max.cri.ci.CiKind.*;
 
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
@@ -88,7 +87,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (value instanceof ConstantNode) {
             CiConstant c = ((ConstantNode) value).asConstant();
             switch (opcode) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatAddNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatAddNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && !y().isConstant()) {
             return graph().unique(new FloatAddNode(kind(), y(), x(), isStrictFP()));
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatDivNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatDivNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && y().isConstant()) {
             if (kind() == CiKind.Float) {
                 return ConstantNode.forFloat(x().asConstant().asFloat() / y().asConstant().asFloat(), graph());
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatMulNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatMulNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && !y().isConstant()) {
             return graph().unique(new FloatMulNode(kind(), y(), x(), isStrictFP()));
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatRemNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatRemNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && y().isConstant()) {
             if (kind() == CiKind.Float) {
                 return ConstantNode.forFloat(x().asConstant().asFloat() % y().asConstant().asFloat(), graph());
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatSubNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/FloatSubNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return ConstantNode.forFloatingKind(kind(), 0.0f, graph());
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerAddNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerAddNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && !y().isConstant()) {
             return graph().unique(new IntegerAddNode(kind(), y(), x()));
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerDivNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerDivNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && y().isConstant()) {
             long yConst = y().asConstant().asLong();
             if (yConst == 0) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerMulNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerMulNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && !y().isConstant()) {
             return graph().unique(new IntegerMulNode(kind(), y(), x()));
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerRemNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerRemNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant() && y().isConstant()) {
             long yConst = y().asConstant().asLong();
             if (yConst == 0) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerSubNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/IntegerSubNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return ConstantNode.forIntegerKind(kind(), 0, graph());
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/LeftShiftNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/LeftShiftNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (y().isConstant()) {
             int amount = y().asConstant().asInt();
             int originalAmout = amount;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/NegateNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/NegateNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.max.graal.nodes.calc;
 
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
@@ -50,7 +49,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant()) {
             switch (x().kind()) {
                 case Int:
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/NullCheckNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/NullCheckNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -23,7 +23,6 @@
 package com.oracle.max.graal.nodes.calc;
 
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
@@ -62,7 +61,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         CiConstant constant = object().asConstant();
         if (constant != null) {
             assert constant.kind == CiKind.Object;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/OrNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/OrNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return x();
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/RightShiftNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/RightShiftNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (y().isConstant()) {
             int amount = y().asConstant().asInt();
             int originalAmout = amount;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/UnsignedRightShiftNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/UnsignedRightShiftNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (y().isConstant()) {
             int amount = y().asConstant().asInt();
             int originalAmout = amount;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/XorNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/calc/XorNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x() == y()) {
             return ConstantNode.forIntegerKind(kind(), 0, graph());
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/Access.java	Tue Jan 17 19:45:39 2012 +0100
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 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.nodes.extended;
+
+import com.oracle.max.graal.nodes.*;
+
+public interface Access {
+
+    ValueNode object();
+
+    LocationNode location();
+
+    void setNullCheck(boolean check);
+}
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/AccessNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/AccessNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -23,16 +23,14 @@
 package com.oracle.max.graal.nodes.extended;
 
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.type.*;
 
-public abstract class AccessNode extends AbstractStateSplit {
+public abstract class AccessNode extends AbstractStateSplit implements Access {
 
     @Input private ValueNode object;
     @Input private GuardNode guard;
     @Input private LocationNode location;
-    @Input private final NodeInputList<Node> dependencies = new NodeInputList<>(this);
     @Data private boolean nullCheck;
 
     public ValueNode object() {
@@ -65,12 +63,4 @@
         this.object = object;
         this.location = location;
     }
-
-    public void addDependency(Node x) {
-        dependencies.add(x);
-    }
-
-    public NodeInputList<Node> dependencies() {
-        return dependencies;
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/FloatingAccessNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011, 2012, 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.nodes.extended;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.calc.*;
+import com.oracle.max.graal.nodes.type.*;
+
+public abstract class FloatingAccessNode extends FloatingNode implements Access {
+
+    @Input private ValueNode object;
+    @Input private GuardNode guard;
+    @Input private LocationNode location;
+    @Data private boolean nullCheck;
+
+    public ValueNode object() {
+        return object;
+    }
+
+    public GuardNode guard() {
+        return guard;
+    }
+
+    public void setGuard(GuardNode x) {
+        updateUsages(guard, x);
+        guard = x;
+    }
+
+    public LocationNode location() {
+        return location;
+    }
+
+    public boolean getNullCheck() {
+        return nullCheck;
+    }
+
+    public void setNullCheck(boolean check) {
+        this.nullCheck = check;
+    }
+
+    public FloatingAccessNode(CiKind kind, ValueNode object, GuardNode guard, LocationNode location) {
+        super(StampFactory.forKind(kind));
+        this.object = object;
+        this.guard = guard;
+        this.location = location;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/FloatingReadNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -0,0 +1,66 @@
+/*
+ * 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.nodes.extended;
+
+import com.oracle.max.cri.ci.*;
+import com.oracle.max.cri.ri.*;
+import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.nodes.*;
+import com.oracle.max.graal.nodes.spi.*;
+
+
+public final class FloatingReadNode extends FloatingAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable {
+
+    @Input private final NodeInputList<Node> dependencies;
+
+    public NodeInputList<Node> dependencies() {
+        return dependencies;
+    }
+
+    public FloatingReadNode(CiKind kind, ValueNode object, GuardNode guard, LocationNode location, Node... dependencies) {
+        super(kind, object, guard, location);
+        this.dependencies = new NodeInputList<>(this, dependencies);
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+        gen.setResult(this, gen.emitLoad(location().createAddress(gen, object()), location().getValueKind(), getNullCheck()));
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (object() != null && object().isConstant() && object().kind() == CiKind.Object) {
+            if (this.location() == LocationNode.FINAL_LOCATION && location().getClass() == LocationNode.class) {
+                Object value = object().asConstant().asObject();
+                long displacement = location().displacement();
+                CiKind kind = location().kind();
+                RiRuntime runtime = tool.runtime();
+                CiConstant constant = kind.readUnsafeConstant(value, displacement);
+                if (constant != null) {
+                    return ConstantNode.forCiConstant(constant, runtime, graph());
+                }
+            }
+        }
+        return this;
+    }
+}
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/IndexedLocationNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/IndexedLocationNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -85,7 +85,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         CiConstant constantIndex = index.asConstant();
         if (constantIndex != null && constantIndex.kind.stackKind().isInt()) {
             long constantIndexLong = constantIndex.asInt();
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/ReadNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/ReadNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.max.graal.nodes.extended;
 
-import sun.misc.*;
-
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.graph.*;
@@ -31,7 +29,7 @@
 import com.oracle.max.graal.nodes.spi.*;
 
 
-public final class ReadNode extends AccessNode implements Node.ValueNumberable, Node.IterableNodeType, LIRLowerable, Canonicalizable {
+public final class ReadNode extends AccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable {
 
     public ReadNode(CiKind kind, ValueNode object, LocationNode location) {
         super(kind, object, location);
@@ -42,13 +40,12 @@
         gen.setResult(this, gen.emitLoad(location().createAddress(gen, object()), location().getValueKind(), getNullCheck()));
     }
 
-
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (object() != null && this.object().isConstant() && this.object().kind() == CiKind.Object) {
-            if (this.location() == LocationNode.FINAL_LOCATION && this.location().getClass() == LocationNode.class) {
-                Object value = this.object().asConstant().asObject();
-                long displacement = this.location().displacement();
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (object() != null && object().isConstant() && object().kind() == CiKind.Object) {
+            if (location() == LocationNode.FINAL_LOCATION && location().getClass() == LocationNode.class) {
+                Object value = object().asConstant().asObject();
+                long displacement = location().displacement();
                 CiKind kind = location().kind();
                 RiRuntime runtime = tool.runtime();
                 CiConstant constant = kind.readUnsafeConstant(value, displacement);
@@ -57,36 +54,6 @@
                 }
             }
         }
-
         return this;
     }
-
-
-
-    public ConstantNode readUnsafeConstant(Object value, long displacement, CiKind kind, RiRuntime runtime) {
-        Unsafe u = Unsafe.getUnsafe();
-        switch(kind) {
-            case Boolean:
-                return ConstantNode.forBoolean(u.getBoolean(value, displacement), graph());
-            case Byte:
-                return ConstantNode.forByte(u.getByte(value, displacement), graph());
-            case Char:
-                return ConstantNode.forChar(u.getChar(value, displacement), graph());
-            case Short:
-                return ConstantNode.forShort(u.getShort(value, displacement), graph());
-            case Int:
-                return ConstantNode.forInt(u.getInt(value, displacement), graph());
-            case Long:
-                return ConstantNode.forLong(u.getLong(value, displacement), graph());
-            case Float:
-                return ConstantNode.forFloat(u.getFloat(value, displacement), graph());
-            case Double:
-                return ConstantNode.forDouble(u.getDouble(value, displacement), graph());
-            case Object:
-                return ConstantNode.forObject(u.getObject(value, displacement), runtime, graph());
-            default:
-                assert false : "unexpected kind: " + kind;
-                return null;
-        }
-    }
 }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/SafeReadNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/SafeReadNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -40,7 +40,7 @@
     public void lower(CiLoweringTool tool) {
         StructuredGraph graph = (StructuredGraph) graph();
         GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(object(), false)));
-        ReadNode read = graph.unique(new ReadNode(kind(), object(), location()));
+        ReadNode read = graph.add(new ReadNode(kind(), object(), location()));
         read.setGuard(guard);
 
         graph.replaceFixedWithFixed(this, read);
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/UnboxNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/UnboxNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -58,7 +58,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (source.isConstant()) {
             CiConstant constant = source.asConstant();
             Object o = constant.asObject();
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/UnsafeCastNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/UnsafeCastNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -24,7 +24,6 @@
 
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.cri.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.calc.*;
 import com.oracle.max.graal.nodes.spi.*;
@@ -49,7 +48,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x != null && x.declaredType() != null && x.declaredType().isSubtypeOf(toType)) {
             return x;
         }
@@ -58,7 +57,7 @@
 
     @Override
     public void lower(CiLoweringTool tool) {
-        replaceAndDelete(x);
+        ((StructuredGraph) graph()).replaceFloating(this, x);
     }
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/UnsafeLoadNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/UnsafeLoadNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -24,7 +24,6 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.graal.cri.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
@@ -32,7 +31,7 @@
 /**
  * Load of a value from a location specified as an offset relative to an object.
  */
-public class UnsafeLoadNode extends AbstractStateSplit implements Lowerable, Node.ValueNumberable {
+public class UnsafeLoadNode extends AbstractStateSplit implements Lowerable {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/ValueAnchorNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/extended/ValueAnchorNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -52,7 +52,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (object == null) {
             return next();
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/ArrayLengthNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/ArrayLengthNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -25,7 +25,6 @@
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
 import com.oracle.max.graal.cri.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
@@ -52,7 +51,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (array() instanceof NewArrayNode) {
             ValueNode length = ((NewArrayNode) array()).dimension(0);
             assert length != null;
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -24,7 +24,6 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.extended.*;
 import com.oracle.max.graal.nodes.spi.*;
@@ -55,7 +54,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         RiResolvedType objectDeclaredType = object().declaredType();
         RiResolvedType targetClass = targetClass();
         if (objectDeclaredType != null && targetClass != null && objectDeclaredType.isSubtypeOf(targetClass)) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -24,7 +24,6 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.calc.*;
 import com.oracle.max.graal.nodes.spi.*;
@@ -55,7 +54,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (object().exactType() != null) {
             boolean result = object().exactType().isSubtypeOf(targetClass());
             if (result != negated) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/IsTypeNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/IsTypeNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -26,7 +26,6 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
@@ -71,7 +70,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (object().exactType() != null) {
             return ConstantNode.forBoolean(object().exactType() == type(), graph());
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/LoadFieldNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/LoadFieldNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -65,7 +65,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         CiConstant constant = null;
         if (isStatic()) {
             constant = field().constantValue(null);
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/MethodCallTargetNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/MethodCallTargetNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -132,7 +132,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (!isStatic()) {
             ValueNode receiver = receiver();
             if (receiver != null && receiver.exactType() != null) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/NewArrayNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/NewArrayNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -126,12 +126,10 @@
                     int index = ((AccessIndexedNode) current).index().asConstant().asInt();
                     if (current instanceof LoadIndexedNode) {
                         x.replaceAtUsages(fieldState[index]);
-                        assert x.usages().size() == 0;
-                        x.replaceAndDelete(x.next());
+                        ((StructuredGraph) x.graph()).removeFixed(x);
                     } else if (current instanceof StoreIndexedNode) {
                         fieldState[index] = ((StoreIndexedNode) x).value();
-                        assert x.usages().size() == 0;
-                        x.replaceAndDelete(x.next());
+                        ((StructuredGraph) x.graph()).removeFixed(x);
                         return index;
                     }
                 }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/NewInstanceNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/NewInstanceNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -100,7 +100,7 @@
         public void beforeUpdate(Node node, Node usage) {
             if (usage instanceof RegisterFinalizerNode) {
                 RegisterFinalizerNode x = (RegisterFinalizerNode) usage;
-                x.replaceAndDelete(x.next());
+                ((StructuredGraph) x.graph()).removeFixed(x);
             } else {
                 super.beforeUpdate(node, usage);
             }
@@ -115,12 +115,10 @@
                     if (current instanceof LoadFieldNode) {
                         assert fieldState[field] != null : field + ", " + ((AccessFieldNode) current).field();
                         x.replaceAtUsages(fieldState[field]);
-                        assert x.usages().size() == 0;
-                        x.replaceAndDelete(x.next());
+                        ((StructuredGraph) x.graph()).removeFixed(x);
                     } else if (current instanceof StoreFieldNode) {
                         fieldState[field] = ((StoreFieldNode) x).value();
-                        assert x.usages().size() == 0;
-                        x.replaceAndDelete(x.next());
+                        ((StructuredGraph) x.graph()).removeFixed(x);
                         return field;
                     }
                 }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/RegisterFinalizerNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/RegisterFinalizerNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -24,7 +24,6 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.spi.*;
 import com.oracle.max.graal.nodes.type.*;
@@ -51,7 +50,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         RiResolvedType declaredType = object.declaredType();
         RiResolvedType exactType = object.exactType();
         if (exactType == null && declaredType != null) {
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/loop/BasicInductionVariableNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/loop/BasicInductionVariableNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -23,7 +23,6 @@
 package com.oracle.max.graal.nodes.loop;
 
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.PhiNode.PhiType;
 import com.oracle.max.graal.nodes.calc.*;
@@ -84,7 +83,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (this.init().isConstant() && this.init().asConstant().asLong() == 0 && this.stride().isConstant() && this.stride().asConstant().asLong() == 1) {
             return this.loopCounter();
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/loop/DerivedInductionVariableNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/loop/DerivedInductionVariableNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -23,7 +23,6 @@
 package com.oracle.max.graal.nodes.loop;
 
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.calc.*;
 import com.oracle.max.graal.nodes.spi.*;
@@ -106,7 +105,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (base() instanceof DerivedInductionVariableNode) {
             DerivedInductionVariableNode divBase = (DerivedInductionVariableNode) base();
             IntegerArithmeticNode newOffset = IntegerArithmeticNode.add(offset(), IntegerArithmeticNode.mul(scale(), divBase.offset()));
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/Canonicalizable.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/Canonicalizable.java	Tue Jan 17 19:45:39 2012 +0100
@@ -22,9 +22,9 @@
  */
 package com.oracle.max.graal.nodes.spi;
 
-import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.nodes.*;
 
 public interface Canonicalizable {
 
-    Node canonical(CanonicalizerTool tool);
+    ValueNode canonical(CanonicalizerTool tool);
 }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/EscapeOp.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/EscapeOp.java	Tue Jan 17 19:45:39 2012 +0100
@@ -102,11 +102,11 @@
         // IsNonNullNode and IsTypeNode should have been eliminated by the CanonicalizerPhase, but we can't rely on this
         if (usage instanceof NullCheckNode) {
             NullCheckNode x = (NullCheckNode) usage;
-            x.replaceAndDelete(ConstantNode.forBoolean(!x.expectedNull, node.graph()));
+            ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(!x.expectedNull, node.graph()));
         } else if (usage instanceof IsTypeNode) {
             IsTypeNode x = (IsTypeNode) usage;
             assert x.type() == ((ValueNode) node).exactType();
-            x.replaceAndDelete(ConstantNode.forBoolean(true, node.graph()));
+            ((StructuredGraph) x.graph()).replaceFloating(x, ConstantNode.forBoolean(true, node.graph()));
         } else if (usage instanceof AccessMonitorNode) {
             ((AccessMonitorNode) usage).makeEliminated();
         }
--- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/util/GraphUtil.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/util/GraphUtil.java	Tue Jan 17 19:45:39 2012 +0100
@@ -65,7 +65,7 @@
     private static void replaceLoopPhis(MergeNode merge) {
         for (Node usage : merge.usages().snapshot()) {
             assert usage instanceof PhiNode;
-            usage.replaceAndDelete(((PhiNode) usage).valueAt(0));
+            ((StructuredGraph) merge.graph()).replaceFloating((PhiNode) usage, ((PhiNode) usage).valueAt(0));
         }
     }
 
--- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/nodes/MathIntrinsicNode.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/nodes/MathIntrinsicNode.java	Tue Jan 17 19:45:39 2012 +0100
@@ -26,7 +26,6 @@
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.target.amd64.*;
 import com.oracle.max.graal.compiler.util.*;
-import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 import com.oracle.max.graal.nodes.calc.*;
 import com.oracle.max.graal.nodes.spi.*;
@@ -75,7 +74,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool) {
         if (x().isConstant()) {
             double value = x().asConstant().asDouble();
             switch (operation()) {
--- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/FloatingReadTest.java	Tue Jan 17 15:28:41 2012 +0100
+++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/FloatingReadTest.java	Tue Jan 17 19:45:39 2012 +0100
@@ -68,9 +68,9 @@
 
         Assert.assertNotNull(returnNode);
         Assert.assertNotNull(monitor);
-        Assert.assertTrue(returnNode.result() instanceof ReadNode);
+        Assert.assertTrue(returnNode.result() instanceof FloatingReadNode);
 
-        ReadNode read = (ReadNode) returnNode.result();
+        FloatingReadNode read = (FloatingReadNode) returnNode.result();
 
         assertOrderedAfterSchedule(graph, read, monitor);
     }