changeset 13167:787357a6de3e

Merge.
author Doug Simon <doug.simon@oracle.com>
date Tue, 26 Nov 2013 00:09:59 +0100
parents 107fee7fa3bb (current diff) 1dd9aa5a9ee5 (diff)
children 533808334e7b
files
diffstat 54 files changed, 654 insertions(+), 241 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java	Tue Nov 26 00:09:59 2013 +0100
@@ -40,4 +40,5 @@
     ArithmeticException,
     RuntimeConstraint,
     LoopLimitCheck,
+    Aliasing,
 }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Nov 26 00:09:59 2013 +0100
@@ -938,6 +938,8 @@
                 Node newInput = duplicationReplacement.replacement(input, true);
                 node.updateUsages(null, newInput);
                 assert Node.verifyUniqueIfExternal(newInput, node.graph());
+                assert newInput == null || fieldTypes.get(inputOffsets[index]).isAssignableFrom(newInput.getClass()) : "Can not assign " + newInput.getClass() + " to " +
+                                fieldTypes.get(inputOffsets[index]) + " in " + node;
                 putNode(node, inputOffsets[index], newInput);
             }
             index++;
@@ -953,6 +955,8 @@
             if (successor != null) {
                 Node newSucc = duplicationReplacement.replacement(successor, false);
                 node.updatePredecessor(null, newSucc);
+                assert newSucc == null || fieldTypes.get(successorOffsets[index]).isAssignableFrom(newSucc.getClass()) : fieldTypes.get(successorOffsets[index]) + " is not compatible with " +
+                                newSucc.getClass();
                 putNode(node, successorOffsets[index], newSucc);
             }
             index++;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Tue Nov 26 00:09:59 2013 +0100
@@ -1129,6 +1129,7 @@
     @HotSpotVMConstant(name = "Deoptimization::Reason_div0_check") @Stable public int deoptReasonDiv0Check;
     @HotSpotVMConstant(name = "Deoptimization::Reason_constraint") @Stable public int deoptReasonConstraint;
     @HotSpotVMConstant(name = "Deoptimization::Reason_loop_limit_check") @Stable public int deoptReasonLoopLimitCheck;
+    @HotSpotVMConstant(name = "Deoptimization::Reason_aliasing") @Stable public int deoptReasonAliasing;
 
     @HotSpotVMConstant(name = "Deoptimization::Action_none") @Stable public int deoptActionNone;
     @HotSpotVMConstant(name = "Deoptimization::Action_maybe_recompile") @Stable public int deoptActionMaybeRecompile;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Tue Nov 26 00:09:59 2013 +0100
@@ -187,6 +187,8 @@
                 return runtime.getConfig().deoptReasonConstraint;
             case LoopLimitCheck:
                 return runtime.getConfig().deoptReasonLoopLimitCheck;
+            case Aliasing:
+                return runtime.getConfig().deoptReasonAliasing;
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
@@ -221,6 +223,8 @@
             return DeoptimizationReason.RuntimeConstraint;
         } else if (reason == runtime.getConfig().deoptReasonLoopLimitCheck) {
             return DeoptimizationReason.LoopLimitCheck;
+        } else if (reason == runtime.getConfig().deoptReasonAliasing) {
+            return DeoptimizationReason.Aliasing;
         } else {
             throw GraalInternalError.shouldNotReachHere(Integer.toHexString(reason));
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -37,7 +37,7 @@
  * is locked (ensuring the GC sees and updates the object) so it must come after any null pointer
  * check on the object.
  */
-public final class BeginLockScopeNode extends AbstractStateSplit implements LIRGenLowerable, MonitorEnter, MemoryCheckpoint.Single {
+public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRGenLowerable, MonitorEnter, MemoryCheckpoint.Single {
 
     private int lockDepth;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -95,4 +95,12 @@
      */
     @NodeIntrinsic
     public static native Word compareAndSwap(Object object, long offset, Word expectedValue, Word newValue, @ConstantNodeParameter LocationIdentity locationIdentity);
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -33,7 +33,7 @@
  * Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an
  * object.
  */
-public final class EndLockScopeNode extends AbstractStateSplit implements LIRGenLowerable, MonitorExit, MemoryCheckpoint.Single {
+public final class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRGenLowerable, MonitorExit, MemoryCheckpoint.Single {
 
     public EndLockScopeNode() {
         super(StampFactory.forVoid());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -83,4 +83,12 @@
         }
         return super.toString(verbosity);
     }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Tue Nov 26 00:09:59 2013 +0100
@@ -246,12 +246,12 @@
                 new_seqInit.inc();
                 explodeLoop();
                 for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) {
-                    memory.writeWord(offset, Word.zero(), INIT_LOCATION);
+                    memory.initializeWord(offset, Word.zero(), INIT_LOCATION);
                 }
             } else {
                 new_loopInit.inc();
                 for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) {
-                    memory.writeWord(offset, Word.zero(), INIT_LOCATION);
+                    memory.initializeWord(offset, Word.zero(), INIT_LOCATION);
                 }
             }
         }
@@ -270,7 +270,7 @@
         initializeObjectHeader(memory, prototypeMarkWord, hub);
         if (fillContents) {
             for (int offset = headerSize; offset < allocationSize; offset += wordSize()) {
-                memory.writeWord(offset, Word.zero(), INIT_LOCATION);
+                memory.initializeWord(offset, Word.zero(), INIT_LOCATION);
             }
         }
         return memory.toObject();
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Tue Nov 26 00:09:59 2013 +0100
@@ -28,7 +28,6 @@
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
 import com.oracle.graal.nodes.VirtualState.VirtualClosure;
 import com.oracle.graal.nodes.cfg.*;
@@ -313,7 +312,20 @@
                 final ValueNode replaceWith;
                 ProxyNode newVpn = getDuplicatedNode(vpn);
                 if (newVpn != null) {
-                    PhiNode phi = graph.addWithoutUnique(vpn.type() == PhiType.Value ? new PhiNode(vpn.kind(), merge) : new PhiNode(vpn.type(), merge, vpn.getIdentity()));
+                    PhiNode phi;
+                    switch (vpn.type()) {
+                        case Value:
+                            phi = graph.addWithoutUnique(new PhiNode(vpn.kind(), merge));
+                            break;
+                        case Guard:
+                            phi = graph.addWithoutUnique(new PhiNode(vpn.type(), merge));
+                            break;
+                        case Memory:
+                            phi = graph.addWithoutUnique(new MemoryPhiNode(merge, ((MemoryProxyNode) vpn).getLocationIdentity()));
+                            break;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere();
+                    }
                     phi.addInput(vpn);
                     phi.addInput(newVpn);
                     replaceWith = phi;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Tue Nov 26 00:09:59 2013 +0100
@@ -166,6 +166,24 @@
         // TODO (gd) ?
     }
 
+    private static PhiNode patchPhi(StructuredGraph graph, PhiNode phi, MergeNode merge) {
+        PhiNode ret;
+        switch (phi.type()) {
+            case Value:
+                ret = new PhiNode(phi.kind(), merge);
+                break;
+            case Guard:
+                ret = new PhiNode(PhiType.Guard, merge);
+                break;
+            case Memory:
+                ret = new MemoryPhiNode(merge, ((MemoryPhiNode) phi).getLocationIdentity());
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        return graph.addWithoutUnique(ret);
+    }
+
     private void patchPeeling(LoopFragmentInside peel) {
         LoopBeginNode loopBegin = loop().loopBegin();
         StructuredGraph graph = loopBegin.graph();
@@ -180,7 +198,7 @@
             }
             // create a new phi (we don't patch the old one since some usages of the old one may
             // still be valid)
-            PhiNode newPhi = graph.addWithoutUnique(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), loopBegin) : new PhiNode(phi.type(), loopBegin, phi.getIdentity()));
+            PhiNode newPhi = patchPhi(graph, phi, loopBegin);
             newPhi.addInput(first);
             for (LoopEndNode end : loopBegin.orderedLoopEnds()) {
                 newPhi.addInput(phi.valueAt(end));
@@ -270,7 +288,7 @@
             }
 
             for (final PhiNode phi : loopBegin.phis().snapshot()) {
-                final PhiNode firstPhi = graph.addWithoutUnique(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), newExitMerge) : new PhiNode(phi.type(), newExitMerge, phi.getIdentity()));
+                final PhiNode firstPhi = patchPhi(graph, phi, newExitMerge);
                 for (AbstractEndNode end : newExitMerge.forwardEnds()) {
                     LoopEndNode loopEnd = reverseEnds.get(end);
                     ValueNode prim = prim(phi.valueAt(loopEnd));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, 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.graal.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+
+public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode {
+
+    @Input private LogicNode condition;
+    private final DeoptimizationReason reason;
+    private final DeoptimizationAction action;
+    private boolean negated;
+
+    public LogicNode condition() {
+        return condition;
+    }
+
+    public void setCondition(LogicNode x) {
+        updateUsages(condition, x);
+        condition = x;
+    }
+
+    protected AbstractFixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
+        super(StampFactory.dependency());
+        this.action = action;
+        this.negated = negated;
+        this.condition = condition;
+        this.reason = deoptReason;
+    }
+
+    public DeoptimizationReason getReason() {
+        return reason;
+    }
+
+    public DeoptimizationAction getAction() {
+        return action;
+    }
+
+    public boolean isNegated() {
+        return negated;
+    }
+
+    @Override
+    public String toString(Verbosity verbosity) {
+        if (verbosity == Verbosity.Name && negated) {
+            return "!" + super.toString(verbosity);
+        } else {
+            return super.toString(verbosity);
+        }
+    }
+
+    @Override
+    public void simplify(SimplifierTool tool) {
+        while (condition instanceof LogicNegationNode) {
+            LogicNegationNode negation = (LogicNegationNode) condition;
+            setCondition(negation.getInput());
+            negated = !negated;
+        }
+    }
+
+    public void lowerToIf() {
+        FixedNode next = next();
+        setNext(null);
+        DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason));
+        deopt.setDeoptimizationState(getDeoptimizationState());
+        IfNode ifNode;
+        AbstractBeginNode noDeoptSuccessor;
+        if (negated) {
+            ifNode = graph().add(new IfNode(condition, deopt, next, 0));
+            noDeoptSuccessor = ifNode.falseSuccessor();
+        } else {
+            ifNode = graph().add(new IfNode(condition, next, deopt, 1));
+            noDeoptSuccessor = ifNode.trueSuccessor();
+        }
+        ((FixedWithNextNode) predecessor()).setNext(ifNode);
+        this.replaceAtUsages(noDeoptSuccessor);
+        GraphUtil.killWithUnusedFloatingInputs(this);
+    }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java	Tue Nov 26 00:09:59 2013 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, 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.graal.nodes;
+
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Provides an implementation of {@link StateSplit}.
+ */
+public abstract class AbstractMemoryCheckpoint extends AbstractStateSplit implements MemoryCheckpoint {
+
+    protected AbstractMemoryCheckpoint(Stamp stamp) {
+        super(stamp);
+    }
+
+    protected AbstractMemoryCheckpoint(Stamp stamp, FrameState stateAfter) {
+        super(stamp, stateAfter);
+    }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -27,78 +27,31 @@
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}")
-public final class FixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable, IterableNodeType, GuardingNode {
-
-    @Input private LogicNode condition;
-    private final DeoptimizationReason reason;
-    private final DeoptimizationAction action;
-    private boolean negated;
-
-    public LogicNode condition() {
-        return condition;
-    }
-
-    public void setCondition(LogicNode x) {
-        updateUsages(condition, x);
-        condition = x;
-    }
+public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType {
 
     public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
         this(condition, deoptReason, action, false);
     }
 
     public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) {
-        super(StampFactory.dependency());
-        this.action = action;
-        this.negated = negated;
-        this.condition = condition;
-        this.reason = deoptReason;
-
-        assert action != null && reason != null;
-    }
-
-    public DeoptimizationReason getReason() {
-        return reason;
-    }
-
-    public DeoptimizationAction getAction() {
-        return action;
-    }
-
-    public boolean isNegated() {
-        return negated;
-    }
-
-    @Override
-    public String toString(Verbosity verbosity) {
-        if (verbosity == Verbosity.Name && negated) {
-            return "!" + super.toString(verbosity);
-        } else {
-            return super.toString(verbosity);
-        }
+        super(condition, deoptReason, action, negated);
     }
 
     @Override
     public void simplify(SimplifierTool tool) {
-        while (condition instanceof LogicNegationNode) {
-            LogicNegationNode negation = (LogicNegationNode) condition;
-            setCondition(negation.getInput());
-            negated = !negated;
-        }
+        super.simplify(tool);
 
-        if (condition instanceof LogicConstantNode) {
-            LogicConstantNode c = (LogicConstantNode) condition;
-            if (c.getValue() == negated) {
+        if (condition() instanceof LogicConstantNode) {
+            LogicConstantNode c = (LogicConstantNode) condition();
+            if (c.getValue() == isNegated()) {
                 FixedNode next = this.next();
                 if (next != null) {
                     tool.deleteBranch(next);
                 }
 
-                DeoptimizeNode deopt = graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, reason));
+                DeoptimizeNode deopt = graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, getReason()));
                 deopt.setDeoptimizationState(getDeoptimizationState());
                 setNext(deopt);
             }
@@ -115,22 +68,7 @@
             ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(guard.asNode()));
             graph().replaceFixedWithFixed(this, newAnchor);
         } else {
-            FixedNode next = next();
-            setNext(null);
-            DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason));
-            deopt.setDeoptimizationState(getDeoptimizationState());
-            IfNode ifNode;
-            AbstractBeginNode noDeoptSuccessor;
-            if (negated) {
-                ifNode = graph().add(new IfNode(condition, deopt, next, 0));
-                noDeoptSuccessor = ifNode.falseSuccessor();
-            } else {
-                ifNode = graph().add(new IfNode(condition, next, deopt, 1));
-                noDeoptSuccessor = ifNode.trueSuccessor();
-            }
-            ((FixedWithNextNode) predecessor()).setNext(ifNode);
-            this.replaceAtUsages(noDeoptSuccessor);
-            GraphUtil.killWithUnusedFloatingInputs(this);
+            lowerToIf();
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -41,7 +42,7 @@
  * control flow would have reached the guarded node (without taking exceptions into account).
  */
 @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}")
-public final class GuardNode extends FloatingGuardedNode implements Canonicalizable, IterableNodeType, GuardingNode, GuardedNode {
+public class GuardNode extends FloatingGuardedNode implements Canonicalizable, IterableNodeType, GuardingNode, GuardedNode {
 
     @Input private LogicNode condition;
     private final DeoptimizationReason reason;
@@ -104,6 +105,20 @@
         return this;
     }
 
+    public FixedWithNextNode lowerGuard() {
+        if (negated() && condition() instanceof IsNullNode) {
+            IsNullNode isNull = (IsNullNode) condition();
+            NullCheckNode nullCheck = graph().add(new NullCheckNode(isNull.object()));
+            setCondition(null);
+            if (isNull.usages().isEmpty()) {
+                isNull.safeDelete();
+            }
+            return nullCheck;
+        }
+
+        return null;
+    }
+
     public void negate() {
         negated = !negated;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -35,7 +35,7 @@
  * The {@code InvokeNode} represents all kinds of method calls.
  */
 @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}")
-public final class InvokeNode extends AbstractStateSplit implements Invoke, LIRLowerable, MemoryCheckpoint.Single {
+public final class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single {
 
     @Input private CallTargetNode callTarget;
     @Input private FrameState deoptState;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -253,4 +253,12 @@
             return stateAfter();
         }
     }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -46,4 +46,12 @@
     public LocationIdentity getLocationIdentity() {
         return locationIdentity;
     }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -23,8 +23,8 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.type.*;
 
 public abstract class MemoryMapNode extends FloatingNode {
@@ -33,5 +33,5 @@
         super(StampFactory.forVoid());
     }
 
-    public abstract Node getLastLocationAccess(LocationIdentity locationIdentity);
+    public abstract MemoryNode getLastLocationAccess(LocationIdentity locationIdentity);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -0,0 +1,51 @@
+/*
+ * 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.graal.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * The {@code PhiNode} represents the merging of dataflow in the memory graph.
+ */
+public class MemoryPhiNode extends PhiNode implements MemoryNode {
+
+    private final LocationIdentity identity;
+
+    public MemoryPhiNode(MergeNode merge, LocationIdentity identity) {
+        super(PhiType.Memory, merge);
+        this.identity = identity;
+    }
+
+    public LocationIdentity getLocationIdentity() {
+        return identity;
+    }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return null;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -0,0 +1,69 @@
+/*
+ * 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.graal.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+
+public class MemoryProxyNode extends ProxyNode implements MemoryProxy, LIRLowerable {
+
+    private final LocationIdentity identity;
+
+    public MemoryProxyNode(ValueNode value, AbstractBeginNode exit, LocationIdentity identity) {
+        super(value, exit, PhiType.Memory);
+        assert value instanceof MemoryNode;
+        this.identity = identity;
+    }
+
+    public LocationIdentity getLocationIdentity() {
+        return identity;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+    }
+
+    @Override
+    public boolean verify() {
+        assert value() instanceof MemoryNode;
+        return super.verify();
+    }
+
+    public static MemoryProxyNode forMemory(MemoryNode value, AbstractBeginNode exit, LocationIdentity location, StructuredGraph graph) {
+        return graph.unique(new MemoryProxyNode(ValueNodeUtil.asNode(value), exit, location));
+    }
+
+    public MemoryNode getOriginalMemoryNode() {
+        return (MemoryNode) value();
+    }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return getOriginalMemoryNode().asMemoryCheckpoint();
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return getOriginalMemoryNode().asMemoryPhi();
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -51,7 +51,6 @@
     @Input(notDataflow = true) private MergeNode merge;
     @Input private final NodeInputList<ValueNode> values = new NodeInputList<>(this);
     private final PhiType type;
-    private final LocationIdentity identity;
 
     /**
      * Create a value phi ({@link PhiType#Value}) with the specified kind.
@@ -68,7 +67,6 @@
         assert stamp != StampFactory.forVoid();
         this.type = PhiType.Value;
         this.merge = merge;
-        this.identity = null;
     }
 
     /**
@@ -77,12 +75,11 @@
      * @param type the type of the new phi
      * @param merge the merge that the new phi belongs to
      */
-    public PhiNode(PhiType type, MergeNode merge, LocationIdentity identity) {
+    public PhiNode(PhiType type, MergeNode merge) {
         super(type.stamp);
         assert type.stamp != null : merge + " " + type;
         this.type = type;
         this.merge = merge;
-        this.identity = identity;
     }
 
     public PhiType type() {
@@ -93,11 +90,6 @@
         return merge;
     }
 
-    public LocationIdentity getIdentity() {
-        assert type != PhiType.Value;
-        return identity;
-    }
-
     public void setMerge(MergeNode x) {
         updateUsages(merge, x);
         merge = x;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.graph.spi.*;
@@ -37,17 +36,15 @@
  * loop.
  */
 @NodeInfo(nameTemplate = "{p#type/s}Proxy")
-public class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable, ValueProxy, GuardingNode {
+public class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, ValueProxy, GuardingNode {
 
     @Input(notDataflow = true) private AbstractBeginNode proxyPoint;
     @Input private ValueNode value;
     private final PhiType type;
-    private final LocationIdentity identity;
 
-    public ProxyNode(ValueNode value, AbstractBeginNode exit, PhiType type, LocationIdentity identity) {
+    public ProxyNode(ValueNode value, AbstractBeginNode exit, PhiType type) {
         super(type == PhiType.Value ? value.stamp() : type.stamp);
         this.type = type;
-        this.identity = identity;
         assert exit != null;
         this.proxyPoint = exit;
         this.value = value;
@@ -70,11 +67,6 @@
         return type;
     }
 
-    public LocationIdentity getIdentity() {
-        assert type != PhiType.Value;
-        return identity;
-    }
-
     @Override
     public boolean verify() {
         assert value != null;
@@ -84,11 +76,6 @@
     }
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
-        assert type == PhiType.Memory;
-    }
-
-    @Override
     public Node canonical(CanonicalizerTool tool) {
         if (type == PhiType.Value && value.isConstant()) {
             return value;
@@ -107,15 +94,11 @@
     }
 
     public static ProxyNode forGuard(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) {
-        return graph.unique(new ProxyNode(value, exit, PhiType.Guard, null));
+        return graph.unique(new ProxyNode(value, exit, PhiType.Guard));
     }
 
     public static ProxyNode forValue(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) {
-        return graph.unique(new ProxyNode(value, exit, PhiType.Value, null));
-    }
-
-    public static ProxyNode forMemory(ValueNode value, AbstractBeginNode exit, LocationIdentity location, StructuredGraph graph) {
-        return graph.unique(new ProxyNode(value, exit, PhiType.Memory, location));
+        return graph.unique(new ProxyNode(value, exit, PhiType.Value));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -34,4 +34,12 @@
     public LocationIdentity getLocationIdentity() {
         return LocationIdentity.ANY_LOCATION;
     }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java	Tue Nov 26 00:09:59 2013 +0100
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.nodes.extended.*;
 
 public class ValueNodeUtil {
 
@@ -95,4 +96,12 @@
     public static String valueString(ValueNode value) {
         return (value == null) ? "-" : ("" + value.kind().getTypeChar() + value.toString(Verbosity.Id));
     }
+
+    public static ValueNode asNode(MemoryNode node) {
+        if (node == null) {
+            return null;
+        } else {
+            return node.asNode();
+        }
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -28,7 +28,7 @@
 /**
  * Base class for nodes that modify a range of an array.
  */
-public abstract class ArrayRangeWriteNode extends AbstractStateSplit {
+public abstract class ArrayRangeWriteNode extends AbstractMemoryCheckpoint {
 
     protected ArrayRangeWriteNode(Stamp stamp) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -43,7 +43,7 @@
         super(object, location, stamp, barrierType, compressible);
     }
 
-    public abstract FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess);
+    public abstract FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess);
 
     /**
      * AccessNodes can float only if their location identities are not ANY_LOCATION. Furthermore, in
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -26,7 +26,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -36,27 +35,27 @@
  */
 public final class FloatingReadNode extends FloatingAccessNode implements IterableNodeType, LIRLowerable, Canonicalizable {
 
-    @Input private Node lastLocationAccess;
+    @Input private MemoryNode lastLocationAccess;
 
-    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp) {
+    public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp) {
         this(object, location, lastLocationAccess, stamp, null, BarrierType.NONE, false);
     }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard) {
+    public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) {
         this(object, location, lastLocationAccess, stamp, guard, BarrierType.NONE, false);
     }
 
-    public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) {
+    public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) {
         super(object, location, stamp, guard, barrierType, compressible);
         this.lastLocationAccess = lastLocationAccess;
     }
 
-    public Node getLastLocationAccess() {
+    public MemoryNode getLastLocationAccess() {
         return lastLocationAccess;
     }
 
-    public void setLastLocationAccess(Node newlla) {
-        updateUsages(lastLocationAccess, newlla);
+    public void setLastLocationAccess(MemoryNode newlla) {
+        updateUsages(ValueNodeUtil.asNode(lastLocationAccess), ValueNodeUtil.asNode(newlla));
         lastLocationAccess = newlla;
     }
 
@@ -76,22 +75,10 @@
         return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), getGuard(), getBarrierType(), isCompressible()));
     }
 
-    private static boolean isMemoryCheckPoint(Node n) {
-        return n instanceof MemoryCheckpoint.Single || n instanceof MemoryCheckpoint.Multi;
-    }
-
-    private static boolean isMemoryPhi(Node n) {
-        return n instanceof PhiNode && ((PhiNode) n).type() == PhiType.Memory;
-    }
-
-    private static boolean isMemoryProxy(Node n) {
-        return n instanceof ProxyNode && ((ProxyNode) n).type() == PhiType.Memory;
-    }
-
     @Override
     public boolean verify() {
-        Node lla = getLastLocationAccess();
-        assert lla == null || isMemoryCheckPoint(lla) || isMemoryPhi(lla) || isMemoryProxy(lla) : "lastLocationAccess of " + this + " should be a MemoryCheckpoint, but is " + lla;
+        MemoryNode lla = getLastLocationAccess();
+        assert lla == null || lla.asMemoryCheckpoint() != null || lla.asMemoryPhi() != null : "lastLocationAccess of " + this + " should be a MemoryCheckpoint, but is " + lla;
         return super.verify();
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -33,7 +33,7 @@
  * Node for a {@linkplain ForeignCallDescriptor foreign} call.
  */
 @NodeInfo(nameTemplate = "ForeignCall#{p#descriptor/s}")
-public class ForeignCallNode extends AbstractStateSplit implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint.Multi {
+public class ForeignCallNode extends AbstractMemoryCheckpoint implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint.Multi {
 
     @Input private final NodeInputList<ValueNode> arguments;
     private final ForeignCallsProvider foreignCalls;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -60,6 +60,14 @@
         generator.emitMembar(barriers);
     }
 
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
+
     @SuppressWarnings("unused")
     @NodeIntrinsic
     public static void memoryBarrier(@ConstantNodeParameter int barriers) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java	Tue Nov 26 00:09:59 2013 +0100
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 
 /**
  * This interface marks nodes that access some memory location, and that have an edge to the last
@@ -33,7 +32,7 @@
 
     LocationIdentity getLocationIdentity();
 
-    Node getLastLocationAccess();
+    MemoryNode getLastLocationAccess();
 
-    void setLastLocationAccess(Node lla);
+    void setLastLocationAccess(MemoryNode lla);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java	Tue Nov 26 00:09:59 2013 +0100
@@ -31,7 +31,9 @@
  * represented by location identities (i.e. change a value at one or more locations that belong to
  * these location identities).
  */
-public interface MemoryCheckpoint {
+public interface MemoryCheckpoint extends MemoryNode {
+
+    FixedNode asNode();
 
     interface Single extends MemoryCheckpoint {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, 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.graal.nodes.extended;
+
+import com.oracle.graal.nodes.*;
+
+/**
+ * This interface marks nodes that are part of the memory graph.
+ */
+public interface MemoryNode {
+
+    ValueNode asNode();
+
+    MemoryCheckpoint asMemoryCheckpoint();
+
+    MemoryPhiNode asMemoryPhi();
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -64,7 +64,7 @@
     }
 
     @Override
-    public FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess) {
+    public FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess) {
         return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getBarrierType(), isCompressible()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -111,6 +111,14 @@
         return stateAfter;
     }
 
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
+
     // specialized on value type until boxing/unboxing is sorted out in intrinsification
 
     @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -102,13 +102,14 @@
         return location().getLocationIdentity();
     }
 
-    public Node getLastLocationAccess() {
-        return lastLocationAccess;
+    public MemoryNode getLastLocationAccess() {
+        return (MemoryNode) lastLocationAccess;
     }
 
-    public void setLastLocationAccess(Node lla) {
-        updateUsages(lastLocationAccess, lla);
-        lastLocationAccess = lla;
+    public void setLastLocationAccess(MemoryNode lla) {
+        Node newLla = ValueNodeUtil.asNode(lla);
+        updateUsages(lastLocationAccess, newLla);
+        lastLocationAccess = newLla;
     }
 
     @Override
@@ -126,4 +127,12 @@
             }
         }
     }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -33,7 +33,7 @@
  * The Java bytecode specification allows non-balanced locking. Graal does not handle such cases and
  * throws a {@link BailoutException} instead during graph building.
  */
-public abstract class AccessMonitorNode extends AbstractStateSplit implements MemoryCheckpoint {
+public abstract class AccessMonitorNode extends AbstractMemoryCheckpoint implements MemoryCheckpoint {
 
     @Input private ValueNode object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -34,7 +34,7 @@
  * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the
  * value matched the expected value.
  */
-public class CompareAndSwapNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint.Single {
+public class CompareAndSwapNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -101,4 +101,12 @@
         assertTrue(stateAfter() != null || stamp() == StampFactory.forVoid(), "an exception handler needs a frame state");
         return super.verify();
     }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -75,4 +75,12 @@
     public void generate(LIRGeneratorTool gen) {
         gen.visitCompareAndSwap(this, location().generateAddress(gen, gen.operand(object())));
     }
+
+    public MemoryCheckpoint asMemoryCheckpoint() {
+        return this;
+    }
+
+    public MemoryPhiNode asMemoryPhi() {
+        return null;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryProxy.java	Tue Nov 26 00:09:59 2013 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, 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.graal.nodes.spi;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.extended.*;
+
+public interface MemoryProxy extends ValueProxy, MemoryNode {
+
+    LocationIdentity getLocationIdentity();
+
+    MemoryNode getOriginalMemoryNode();
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Tue Nov 26 00:09:59 2013 +0100
@@ -28,7 +28,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
@@ -43,7 +42,7 @@
 
     public static class MemoryMapImpl extends MemoryMapNode {
 
-        private IdentityHashMap<LocationIdentity, ValueNode> lastMemorySnapshot;
+        private IdentityHashMap<LocationIdentity, MemoryNode> lastMemorySnapshot;
 
         public MemoryMapImpl(MemoryMapImpl memoryMap) {
             lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot);
@@ -59,8 +58,8 @@
         }
 
         @Override
-        public ValueNode getLastLocationAccess(LocationIdentity locationIdentity) {
-            ValueNode lastLocationAccess;
+        public MemoryNode getLastLocationAccess(LocationIdentity locationIdentity) {
+            MemoryNode lastLocationAccess;
             if (locationIdentity == FINAL_LOCATION) {
                 return null;
             } else {
@@ -198,7 +197,7 @@
         private static void processAccess(MemoryAccess access, MemoryMapImpl state) {
             LocationIdentity locationIdentity = access.getLocationIdentity();
             if (locationIdentity != LocationIdentity.ANY_LOCATION) {
-                ValueNode lastLocationAccess = state.getLastLocationAccess(locationIdentity);
+                MemoryNode lastLocationAccess = state.getLastLocationAccess(locationIdentity);
                 access.setLastLocationAccess(lastLocationAccess);
             }
         }
@@ -217,7 +216,7 @@
             if (identity == ANY_LOCATION) {
                 state.lastMemorySnapshot.clear();
             }
-            state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint);
+            state.lastMemorySnapshot.put(identity, checkpoint);
         }
 
         private static void processFloatable(FloatableAccessNode accessNode, MemoryMapImpl state) {
@@ -225,7 +224,7 @@
             assert accessNode.getNullCheck() == false;
             LocationIdentity locationIdentity = accessNode.location().getLocationIdentity();
             if (accessNode.canFloat()) {
-                ValueNode lastLocationAccess = state.getLastLocationAccess(locationIdentity);
+                MemoryNode lastLocationAccess = state.getLastLocationAccess(locationIdentity);
                 FloatingAccessNode floatingNode = accessNode.asFloatingNode(lastLocationAccess);
                 floatingNode.setNullCheck(accessNode.getNullCheck());
                 ValueAnchorNode anchor = null;
@@ -251,22 +250,22 @@
             for (LocationIdentity key : keys) {
                 int mergedStatesCount = 0;
                 boolean isPhi = false;
-                ValueNode merged = null;
+                MemoryNode merged = null;
                 for (MemoryMapImpl state : states) {
-                    ValueNode last = state.getLastLocationAccess(key);
+                    MemoryNode last = state.getLastLocationAccess(key);
                     if (isPhi) {
-                        ((PhiNode) merged).addInput(last);
+                        merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last));
                     } else {
                         if (merged == last) {
                             // nothing to do
                         } else if (merged == null) {
                             merged = last;
                         } else {
-                            PhiNode phi = merge.graph().addWithoutUnique(new PhiNode(PhiType.Memory, merge, key));
+                            MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key));
                             for (int j = 0; j < mergedStatesCount; j++) {
-                                phi.addInput(merged);
+                                phi.addInput(ValueNodeUtil.asNode(merged));
                             }
-                            phi.addInput(last);
+                            phi.addInput(ValueNodeUtil.asNode(last));
                             merged = phi;
                             isPhi = true;
                         }
@@ -290,7 +289,7 @@
                  * side it needs to choose by putting in the location identity on both successors.
                  */
                 InvokeWithExceptionNode invoke = (InvokeWithExceptionNode) node.predecessor();
-                result.lastMemorySnapshot.put(invoke.getLocationIdentity(), node);
+                result.lastMemorySnapshot.put(invoke.getLocationIdentity(), (MemoryCheckpoint) node);
             }
             return result;
         }
@@ -306,8 +305,8 @@
 
             Map<LocationIdentity, PhiNode> phis = new HashMap<>();
             for (LocationIdentity location : modifiedLocations) {
-                PhiNode phi = loop.graph().addWithoutUnique(new PhiNode(PhiType.Memory, loop, location));
-                phi.addInput(initialState.getLastLocationAccess(location));
+                MemoryPhiNode phi = loop.graph().addWithoutUnique(new MemoryPhiNode(loop, location));
+                phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(location)));
                 phis.put(location, phi);
                 initialState.lastMemorySnapshot.put(location, phi);
             }
@@ -319,16 +318,16 @@
                 for (Map.Entry<LocationIdentity, PhiNode> phiEntry : phis.entrySet()) {
                     LocationIdentity key = phiEntry.getKey();
                     PhiNode phi = phiEntry.getValue();
-                    phi.initializeValueAt(endIndex, entry.getValue().getLastLocationAccess(key));
+                    phi.initializeValueAt(endIndex, ValueNodeUtil.asNode(entry.getValue().getLastLocationAccess(key)));
                 }
             }
             for (Map.Entry<LoopExitNode, MemoryMapImpl> entry : loopInfo.exitStates.entrySet()) {
                 LoopExitNode exit = entry.getKey();
                 MemoryMapImpl state = entry.getValue();
                 for (LocationIdentity location : modifiedLocations) {
-                    ValueNode lastAccessAtExit = state.lastMemorySnapshot.get(location);
+                    MemoryNode lastAccessAtExit = state.lastMemorySnapshot.get(location);
                     if (lastAccessAtExit != null) {
-                        state.lastMemorySnapshot.put(location, ProxyNode.forMemory(lastAccessAtExit, exit, location, loop.graph()));
+                        state.lastMemorySnapshot.put(location, MemoryProxyNode.forMemory(lastAccessAtExit, exit, location, loop.graph()));
                     }
                 }
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Tue Nov 26 00:09:59 2013 +0100
@@ -142,8 +142,9 @@
         protected void processNode(Node node) {
             if (node instanceof GuardNode) {
                 GuardNode guard = (GuardNode) node;
-                if (guard.negated() && guard.condition() instanceof IsNullNode) {
-                    lowerToNullCheck(guard);
+                FixedWithNextNode lowered = guard.lowerGuard();
+                if (lowered != null) {
+                    replaceCurrent(lowered);
                 } else {
                     lowerToIf(guard);
                 }
@@ -171,15 +172,6 @@
             insert(ifNode, fastPath);
         }
 
-        private void lowerToNullCheck(GuardNode guard) {
-            IsNullNode isNull = (IsNullNode) guard.condition();
-            NullCheckNode nullCheck = guard.graph().add(new NullCheckNode(isNull.object()));
-            replaceCurrent(nullCheck);
-            if (isNull.usages().isEmpty()) {
-                isNull.safeDelete();
-            }
-        }
-
         private void insertLoopExits(DeoptimizeNode deopt) {
             Loop loop = block.getLoop();
             StructuredGraph graph = deopt.graph();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java	Tue Nov 26 00:09:59 2013 +0100
@@ -72,7 +72,7 @@
             }
         }
         for (ControlSplitNode controlSplit : graph.getNodes(ControlSplitNode.class)) {
-            otpimizeAtControlSplit(controlSplit, cfg);
+            optimizeAtControlSplit(controlSplit, cfg);
         }
     }
 
@@ -84,7 +84,7 @@
         return anchor.getBeginNode();
     }
 
-    private static void otpimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) {
+    private static void optimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) {
         AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit);
         int successorCount = controlSplit.successors().count();
         List<GuardNode> otherGuards = new ArrayList<>(successorCount - 1);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java	Tue Nov 26 00:09:59 2013 +0100
@@ -46,24 +46,24 @@
         return isWrites(n, n.getLastLocationAccess(), n.graph().createNodeBitMap());
     }
 
-    private static boolean isWrites(FloatingReadNode n, Node lastLocationAccess, NodeBitMap visited) {
+    private static boolean isWrites(FloatingReadNode n, MemoryNode lastLocationAccess, NodeBitMap visited) {
         if (lastLocationAccess == null) {
             return false;
         }
-        if (visited.isMarked(lastLocationAccess)) {
+        if (visited.isMarked(ValueNodeUtil.asNode(lastLocationAccess))) {
             return true; // dataflow loops must come from Phis assume them ok until proven wrong
         }
         if (lastLocationAccess instanceof ProxyNode) {
-            return isWrites(n, ((ProxyNode) lastLocationAccess).value(), visited);
+            return isWrites(n, (MemoryNode) ((ProxyNode) lastLocationAccess).value(), visited);
         }
         if (lastLocationAccess instanceof WriteNode) {
             WriteNode other = (WriteNode) lastLocationAccess;
             return other.object() == n.object() && other.location() == n.location();
         }
         if (lastLocationAccess instanceof PhiNode) {
-            visited.mark(lastLocationAccess);
+            visited.mark(ValueNodeUtil.asNode(lastLocationAccess));
             for (ValueNode value : ((PhiNode) lastLocationAccess).values()) {
-                if (!isWrites(n, value, visited)) {
+                if (!isWrites(n, (MemoryNode) value, visited)) {
                     return false;
                 }
             }
@@ -72,15 +72,15 @@
         return false;
     }
 
-    private static ValueNode getValue(FloatingReadNode n, Node lastLocationAccess, NodeMap<ValueNode> nodeMap) {
-        ValueNode exisiting = nodeMap.get(lastLocationAccess);
+    private static ValueNode getValue(FloatingReadNode n, MemoryNode lastLocationAccess, NodeMap<ValueNode> nodeMap) {
+        ValueNode exisiting = nodeMap.get(ValueNodeUtil.asNode(lastLocationAccess));
         if (exisiting != null) {
             return exisiting;
         }
-        if (lastLocationAccess instanceof ProxyNode) {
-            ProxyNode proxy = (ProxyNode) lastLocationAccess;
-            ValueNode value = getValue(n, proxy.value(), nodeMap);
-            return ProxyNode.forValue(value, proxy.proxyPoint(), (StructuredGraph) lastLocationAccess.graph());
+        if (lastLocationAccess instanceof MemoryProxyNode) {
+            MemoryProxyNode proxy = (MemoryProxyNode) lastLocationAccess;
+            ValueNode value = getValue(n, proxy.getOriginalMemoryNode(), nodeMap);
+            return ProxyNode.forValue(value, proxy.proxyPoint(), proxy.graph());
         }
         if (lastLocationAccess instanceof WriteNode) {
             return ((WriteNode) lastLocationAccess).value();
@@ -88,9 +88,9 @@
         if (lastLocationAccess instanceof PhiNode) {
             PhiNode phi = (PhiNode) lastLocationAccess;
             PhiNode newPhi = phi.graph().addWithoutUnique(new PhiNode(n.kind(), phi.merge()));
-            nodeMap.set(lastLocationAccess, newPhi);
+            nodeMap.set(phi, newPhi);
             for (ValueNode value : phi.values()) {
-                newPhi.addInput(getValue(n, value, nodeMap));
+                newPhi.addInput(getValue(n, (MemoryNode) value, nodeMap));
             }
             return newPhi;
         }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Nov 26 00:09:59 2013 +0100
@@ -33,7 +33,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
@@ -286,14 +285,12 @@
         KillSet excludedLocations = new KillSet();
         if (block.getBeginNode() instanceof MergeNode) {
             MergeNode mergeNode = (MergeNode) block.getBeginNode();
-            for (PhiNode phi : mergeNode.usages().filter(PhiNode.class)) {
-                if (phi.type() == PhiType.Memory) {
-                    if (foundExcludeNode) {
-                        set.add(phi.getIdentity());
-                    } else {
-                        excludedLocations.add(phi.getIdentity());
-                        foundExcludeNode = phi == excludeNode;
-                    }
+            for (MemoryPhiNode phi : mergeNode.usages().filter(MemoryPhiNode.class)) {
+                if (foundExcludeNode) {
+                    set.add(phi.getLocationIdentity());
+                } else {
+                    excludedLocations.add(phi.getLocationIdentity());
+                    foundExcludeNode = phi == excludeNode;
                 }
             }
         }
@@ -403,8 +400,12 @@
         }
     }
 
-    private Block blockForFixedNode(Node n) {
-        Block b = cfg.getNodeToBlock().get(n);
+    private Block blockForMemoryNode(MemoryNode memory) {
+        MemoryNode current = memory;
+        while (current instanceof MemoryProxy) {
+            current = ((MemoryProxy) current).getOriginalMemoryNode();
+        }
+        Block b = cfg.getNodeToBlock().get(current.asNode());
         assert b != null : "all lastAccess locations should have a block assignment from CFG";
         return b;
     }
@@ -546,13 +547,11 @@
                 if (assertionEnabled()) {
                     if (scheduleRead) {
                         FloatingReadNode read = (FloatingReadNode) node;
-                        Node lastLocationAccess = read.getLastLocationAccess();
-                        Block upperBound = blockForFixedNode(lastLocationAccess);
-                        if (!blockForFixedNode(lastLocationAccess).dominates(block)) {
-                            assert false : String.format("out of loop movement voilated memory semantics for %s (location %s). moved to %s but upper bound is %s (earliest: %s, latest: %s)", read,
-                                            read.getLocationIdentity(), block, upperBound, earliestBlock, latest);
-                        }
-
+                        MemoryNode lastLocationAccess = read.getLastLocationAccess();
+                        Block upperBound = blockForMemoryNode(lastLocationAccess);
+                        assert upperBound.dominates(block) : String.format(
+                                        "out of loop movement voilated memory semantics for %s (location %s). moved to %s but upper bound is %s (earliest: %s, latest: %s)", read,
+                                        read.getLocationIdentity(), block, upperBound, earliestBlock, latest);
                     }
                 }
                 break;
@@ -599,7 +598,7 @@
         LocationIdentity locid = n.location().getLocationIdentity();
         assert locid != FINAL_LOCATION;
 
-        Block upperBoundBlock = blockForFixedNode(n.getLastLocationAccess());
+        Block upperBoundBlock = blockForMemoryNode(n.getLastLocationAccess());
         Block earliestBlock = earliestBlock(n);
         assert upperBoundBlock.dominates(earliestBlock) : "upper bound (" + upperBoundBlock + ") should dominate earliest (" + earliestBlock + ")";
 
@@ -630,7 +629,7 @@
                 if (currentBlock == upperBoundBlock) {
                     assert earliestBlock == upperBoundBlock;
                     // don't treat lastLocationAccess node as a kill for this read.
-                    closure = new NewMemoryScheduleClosure(n.getLastLocationAccess(), upperBoundBlock);
+                    closure = new NewMemoryScheduleClosure(ValueNodeUtil.asNode(n.getLastLocationAccess()), upperBoundBlock);
                 } else {
                     closure = new NewMemoryScheduleClosure();
                 }
@@ -646,7 +645,7 @@
             } else {
                 if (currentBlock == upperBoundBlock) {
                     assert earliestBlock == upperBoundBlock;
-                    KillSet ks = computeKillSet(upperBoundBlock, n.getLastLocationAccess());
+                    KillSet ks = computeKillSet(upperBoundBlock, ValueNodeUtil.asNode(n.getLastLocationAccess()));
                     if (ks.isKilled(locid)) {
                         return upperBoundBlock;
                     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Tue Nov 26 00:09:59 2013 +0100
@@ -380,7 +380,7 @@
         } else if (usage instanceof ProxyNode) {
             ProxyNode proxy = (ProxyNode) usage;
             assert proxy.type() == PhiType.Value;
-            ProxyNode newProxy = graph.unique(new ProxyNode((ValueNode) intrinsifiedNode, proxy.proxyPoint(), PhiType.Value, proxy.getIdentity()));
+            ProxyNode newProxy = graph.unique(new ProxyNode((ValueNode) intrinsifiedNode, proxy.proxyPoint(), PhiType.Value));
             for (Node proxyUsage : usage.usages().snapshot()) {
                 checkCheckCastUsage(graph, newProxy, proxy, proxyUsage);
             }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Nov 26 00:09:59 2013 +0100
@@ -854,25 +854,43 @@
      */
     public static final UsageReplacer DEFAULT_REPLACER = new UsageReplacer() {
 
+        private LocationIdentity getLocationIdentity(Node node) {
+            if (node instanceof MemoryAccess) {
+                return ((MemoryAccess) node).getLocationIdentity();
+            } else if (node instanceof MemoryProxy) {
+                return ((MemoryProxy) node).getLocationIdentity();
+            } else if (node instanceof MemoryPhiNode) {
+                return ((MemoryPhiNode) node).getLocationIdentity();
+            } else {
+                return null;
+            }
+        }
+
         @Override
         public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) {
-            oldNode.replaceAtUsages(newNode);
-            if (mmap == null || newNode == null) {
-                return;
-            }
-            for (Node usage : newNode.usages().snapshot()) {
-                if (usage instanceof FloatingReadNode && ((FloatingReadNode) usage).getLastLocationAccess() == newNode) {
-                    assert newNode.graph().isAfterFloatingReadPhase();
+            if (mmap != null && newNode != null) {
+                for (Node usage : oldNode.usages().snapshot()) {
+                    LocationIdentity identity = getLocationIdentity(usage);
+                    if (identity != null && identity != LocationIdentity.FINAL_LOCATION) {
+                        // lastLocationAccess points into the snippet graph. find a proper
+                        // MemoryCheckPoint inside the snippet graph
+                        MemoryNode lastAccess = mmap.getLastLocationAccess(identity);
 
-                    // lastLocationAccess points into the snippet graph. find a proper
-                    // MemoryCheckPoint inside the snippet graph
-                    FloatingReadNode read = (FloatingReadNode) usage;
-                    Node lastAccess = mmap.getLastLocationAccess(read.location().getLocationIdentity());
-
-                    assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)";
-                    read.setLastLocationAccess(lastAccess);
+                        assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)";
+                        if (usage instanceof MemoryAccess) {
+                            MemoryAccess access = (MemoryAccess) usage;
+                            if (access.getLastLocationAccess() == oldNode) {
+                                assert newNode.graph().isAfterFloatingReadPhase();
+                                access.setLastLocationAccess(lastAccess);
+                            }
+                        } else {
+                            assert usage instanceof MemoryProxy || usage instanceof MemoryPhiNode;
+                            usage.replaceFirstInput(oldNode, lastAccess.asNode());
+                        }
+                    }
                 }
             }
+            oldNode.replaceAtUsages(newNode);
         }
     };
 
@@ -933,14 +951,14 @@
         }
 
         @Override
-        public Node getLastLocationAccess(LocationIdentity locationIdentity) {
+        public MemoryNode getLastLocationAccess(LocationIdentity locationIdentity) {
             assert memoryMap != null : "no memory map stored for this snippet graph (snippet doesn't have a ReturnNode?)";
-            Node lastLocationAccess = memoryMap.getLastLocationAccess(locationIdentity);
+            MemoryNode lastLocationAccess = memoryMap.getLastLocationAccess(locationIdentity);
             assert lastLocationAccess != null;
             if (lastLocationAccess instanceof StartNode) {
                 return replaceeStart;
             } else {
-                return duplicates.get(lastLocationAccess);
+                return (MemoryNode) duplicates.get(ValueNodeUtil.asNode(lastLocationAccess));
             }
         }
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Tue Nov 26 00:09:59 2013 +0100
@@ -37,7 +37,7 @@
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
-public class MacroNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint.Single {
+public class MacroNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
     @Input protected final NodeInputList<ValueNode> arguments;
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Tue Nov 26 00:09:59 2013 +0100
@@ -114,7 +114,7 @@
             if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
                 ValueNode value = exitState.getReadCache(entry.getKey().object, entry.getKey().identity, this);
                 if (!(value instanceof ProxyNode) || ((ProxyNode) value).proxyPoint() != exitNode) {
-                    ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value, null);
+                    ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value);
                     effects.addFloatingNode(proxy, "readCacheProxy");
                     entry.setValue(proxy);
                 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Tue Nov 26 00:09:59 2013 +0100
@@ -247,7 +247,7 @@
                     ValueNode value = obj.getEntry(i);
                     if (!(value instanceof VirtualObjectNode || value.isConstant())) {
                         if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) {
-                            ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value, null);
+                            ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value);
                             obj.setEntry(i, proxy);
                             effects.addFloatingNode(proxy, "virtualProxy");
                         }
@@ -257,7 +257,7 @@
                 if (initialObj == null || initialObj.isVirtual()) {
                     ProxyNode proxy = proxies.get(obj.virtual);
                     if (proxy == null) {
-                        proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value, null);
+                        proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value);
                         effects.addFloatingNode(proxy, "proxy");
                     } else {
                         effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue());
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Tue Nov 26 00:09:17 2013 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Tue Nov 26 00:09:59 2013 +0100
@@ -171,7 +171,7 @@
     protected void processLoopExit(LoopExitNode exitNode, ReadEliminationBlockState initialState, ReadEliminationBlockState exitState, GraphEffectList effects) {
         for (Map.Entry<CacheEntry<?>, ValueNode> entry : exitState.getReadCache().entrySet()) {
             if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
-                ProxyNode proxy = new ProxyNode(exitState.getCacheEntry(entry.getKey()), exitNode, PhiType.Value, null);
+                ProxyNode proxy = new ProxyNode(exitState.getCacheEntry(entry.getKey()), exitNode, PhiType.Value);
                 effects.addFloatingNode(proxy, "readCacheProxy");
                 entry.setValue(proxy);
             }
--- a/src/share/vm/runtime/deoptimization.hpp	Tue Nov 26 00:09:17 2013 +0100
+++ b/src/share/vm/runtime/deoptimization.hpp	Tue Nov 26 00:09:59 2013 +0100
@@ -72,6 +72,9 @@
     Reason_age,                   // nmethod too old; tier threshold reached
     Reason_predicate,             // compiler generated predicate failed
     Reason_loop_limit_check,      // compiler generated loop limits check failed
+#ifdef GRAAL
+    Reason_aliasing,              // optimistic assumption about aliasing failed
+#endif
     Reason_LIMIT,
 
 #ifdef GRAAL
--- a/src/share/vm/runtime/vmStructs.cpp	Tue Nov 26 00:09:17 2013 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Tue Nov 26 00:09:59 2013 +0100
@@ -2196,7 +2196,8 @@
                          declare_preprocessor_constant,                   \
                          declare_c1_constant,                             \
                          declare_c2_constant,                             \
-                         declare_c2_preprocessor_constant)                \
+                         declare_c2_preprocessor_constant,                \
+                         declare_graal_constant)                          \
                                                                           \
   /******************/                                                    \
   /* Useful globals */                                                    \
@@ -2505,6 +2506,7 @@
   declare_constant(Deoptimization::Reason_age)                            \
   declare_constant(Deoptimization::Reason_predicate)                      \
   declare_constant(Deoptimization::Reason_loop_limit_check)               \
+  declare_graal_constant(Deoptimization::Reason_aliasing)                 \
   declare_constant(Deoptimization::Reason_LIMIT)                          \
   declare_constant(Deoptimization::Reason_RECORDED_LIMIT)                 \
                                                                           \
@@ -2867,6 +2869,13 @@
 # define GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY(name, value)
 #endif /* COMPILER1 */
 
+// Generate an int constant for a Graal build
+#ifdef GRAAL
+# define GENERATE_GRAAL_VM_INT_CONSTANT_ENTRY(name)  GENERATE_VM_INT_CONSTANT_ENTRY(name)
+#else
+# define GENERATE_GRAAL_VM_INT_CONSTANT_ENTRY(name)
+#endif
+
 //--------------------------------------------------------------------------------
 // VMLongConstantEntry macros
 //
@@ -3009,7 +3018,8 @@
                    GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY,
                    GENERATE_C1_VM_INT_CONSTANT_ENTRY,
                    GENERATE_C2_VM_INT_CONSTANT_ENTRY,
-                   GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
+                   GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY,
+                   GENERATE_GRAAL_VM_INT_CONSTANT_ENTRY)
 
 #if INCLUDE_ALL_GCS
   VM_INT_CONSTANTS_CMS(GENERATE_VM_INT_CONSTANT_ENTRY)