changeset 19626:cb701331de39

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 27 Feb 2015 16:36:38 +0100
parents afad10e79e13 (current diff) 73811d1b4cd0 (diff)
children 7b42a78ea270
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMonitorValue.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java
diffstat 45 files changed, 435 insertions(+), 353 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/StackLockValue.java	Fri Feb 27 16:36:38 2015 +0100
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2011, 2015, 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.api.code;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Represents lock information in the debug information.
+ */
+public final class StackLockValue extends AbstractValue implements JavaValue {
+
+    private static final long serialVersionUID = 8241681800464483691L;
+
+    private JavaValue owner;
+    private StackSlotValue slot;
+    private final boolean eliminated;
+
+    public StackLockValue(JavaValue owner, StackSlotValue slot, boolean eliminated) {
+        super(LIRKind.Illegal);
+        this.owner = owner;
+        this.slot = slot;
+        this.eliminated = eliminated;
+    }
+
+    public JavaValue getOwner() {
+        return owner;
+    }
+
+    public void setOwner(JavaValue newOwner) {
+        this.owner = newOwner;
+    }
+
+    public Value getSlot() {
+        return slot;
+    }
+
+    public boolean isEliminated() {
+        return eliminated;
+    }
+
+    @Override
+    public String toString() {
+        return "monitor[" + owner + (slot != null ? ", " + slot : "") + (eliminated ? ", eliminated" : "") + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 43;
+        int result = super.hashCode();
+        result = prime * result + (eliminated ? 1231 : 1237);
+        result = prime * result + owner.hashCode();
+        result = prime * result + slot.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof StackLockValue) {
+            StackLockValue other = (StackLockValue) obj;
+            return super.equals(obj) && eliminated == other.eliminated && owner.equals(other.owner) && slot.equals(other.slot);
+        }
+        return false;
+    }
+
+    public void setSlot(StackSlotValue stackSlot) {
+        assert slot == null || (isVirtualStackSlot(slot) && (slot.equals(stackSlot) || isStackSlot(stackSlot))) : String.format("Can not set slot for %s to %s", this, stackSlot);
+        slot = stackSlot;
+    }
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Fri Feb 27 16:36:38 2015 +0100
@@ -41,6 +41,7 @@
 import com.oracle.graal.graph.Node.OptionalInput;
 import com.oracle.graal.graph.Node.Successor;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.nodeinfo.*;
 
 /**
@@ -118,6 +119,11 @@
     private final boolean isCanonicalizable;
 
     /**
+     * Determines if this node type implements {@link BinaryCommutative}.
+     */
+    private final boolean isCommutative;
+
+    /**
      * Determines if this node type implements {@link Simplifiable}.
      */
     private final boolean isSimplifiable;
@@ -133,6 +139,7 @@
         assert NODE_CLASS.isAssignableFrom(clazz);
 
         this.isCanonicalizable = Canonicalizable.class.isAssignableFrom(clazz);
+        this.isCommutative = BinaryCommutative.class.isAssignableFrom(clazz);
         if (Canonicalizable.Unary.class.isAssignableFrom(clazz) || Canonicalizable.Binary.class.isAssignableFrom(clazz)) {
             assert Canonicalizable.Unary.class.isAssignableFrom(clazz) ^ Canonicalizable.Binary.class.isAssignableFrom(clazz) : clazz + " should implement either Unary or Binary, not both";
         }
@@ -238,6 +245,13 @@
     }
 
     /**
+     * Determines if this node type implements {@link BinaryCommutative}.
+     */
+    public boolean isCommutative() {
+        return isCommutative;
+    }
+
+    /**
      * Determines if this node type implements {@link Simplifiable}.
      */
     public boolean isSimplifiable() {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java	Fri Feb 27 16:36:38 2015 +0100
@@ -128,4 +128,22 @@
             return canonical(tool, getX(), getY());
         }
     }
+
+    /**
+     * This sub-interface of {@link Canonicalizable.Binary} is for nodes with two inputs where the
+     * operation is commutative. It is used to improve GVN by trying to merge nodes with the same
+     * inputs in different order.
+     */
+    public interface BinaryCommutative<T extends Node> extends Binary<T> {
+
+        /**
+         * Ensure a canonical ordering of inputs for commutative nodes to improve GVN results. Order
+         * the inputs by increasing {@link Node#id} and call {@link Graph#findDuplicate(Node)} on
+         * the node if it's currently in a graph. It's assumed that if there was a constant on the
+         * left it's been moved to the right by other code and that ordering is left alone.
+         *
+         * @return the original node or another node with the same input ordering
+         */
+        Node maybeCommuteInputs();
+    }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Fri Feb 27 16:36:38 2015 +0100
@@ -93,14 +93,14 @@
 
     @SuppressWarnings("unused")
     private static Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) {
-        List<Register> callerSaveRegisters = new ArrayList<>();
-        Collections.addAll(callerSaveRegisters, regConfig.getCallerSaveRegisters());
-        // TODO: Saving callee saved registers as well seems unneccessary, however as of now it does
-        // not work without; needs further investigation
-        Collections.addAll(callerSaveRegisters, regConfig.getCalleeSaveLayout().registers);
-        Value[] nativeABICallerSaveRegisters = new Value[callerSaveRegisters.size()];
-        for (int i = 0; i < callerSaveRegisters.size(); i++) {
-            nativeABICallerSaveRegisters[i] = callerSaveRegisters.get(i).asValue();
+        Set<Register> callerSavedRegisters = new HashSet<>();
+        Collections.addAll(callerSavedRegisters, regConfig.getCalleeSaveLayout().registers);
+        Collections.addAll(callerSavedRegisters, SPARC.fpuRegisters);
+        Value[] nativeABICallerSaveRegisters = new Value[callerSavedRegisters.size()];
+        int i = 0;
+        for (Register reg : callerSavedRegisters) {
+            nativeABICallerSaveRegisters[i] = reg.asValue();
+            i++;
         }
         return nativeABICallerSaveRegisters;
     }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java	Fri Feb 27 16:36:38 2015 +0100
@@ -35,7 +35,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.test.*;
-import com.oracle.graal.hotspot.meta.*;
 
 public class HotSpotMonitorValueTest extends GraalCompilerTest {
 
@@ -53,14 +52,14 @@
                         assertNull(caller.caller());
                         assertDeepEquals(2, frame.numLocks);
                         assertDeepEquals(2, caller.numLocks);
-                        HotSpotMonitorValue lock1 = (HotSpotMonitorValue) frame.getLockValue(0);
-                        HotSpotMonitorValue lock2 = (HotSpotMonitorValue) frame.getLockValue(1);
-                        HotSpotMonitorValue lock3 = (HotSpotMonitorValue) caller.getLockValue(0);
-                        HotSpotMonitorValue lock4 = (HotSpotMonitorValue) caller.getLockValue(1);
+                        StackLockValue lock1 = (StackLockValue) frame.getLockValue(0);
+                        StackLockValue lock2 = (StackLockValue) frame.getLockValue(1);
+                        StackLockValue lock3 = (StackLockValue) caller.getLockValue(0);
+                        StackLockValue lock4 = (StackLockValue) caller.getLockValue(1);
 
-                        List<HotSpotMonitorValue> locks = Arrays.asList(lock1, lock2, lock3, lock4);
-                        for (HotSpotMonitorValue lock : locks) {
-                            for (HotSpotMonitorValue other : locks) {
+                        List<StackLockValue> locks = Arrays.asList(lock1, lock2, lock3, lock4);
+                        for (StackLockValue lock : locks) {
+                            for (StackLockValue other : locks) {
                                 if (other != lock) {
                                     // Every lock must have a different stack slot
                                     assertThat(lock.getSlot(), not(other.getSlot()));
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java	Fri Feb 27 16:36:38 2015 +0100
@@ -26,7 +26,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.nodes.*;
 
@@ -57,7 +56,7 @@
         JavaValue object = toValue(lock);
         boolean eliminated = object instanceof VirtualObject && state.monitorIdAt(lockIndex) != null;
         assert state.monitorIdAt(lockIndex) == null || state.monitorIdAt(lockIndex).getLockDepth() == lockDepth;
-        return new HotSpotMonitorValue(object, slot, eliminated);
+        return new StackLockValue(object, slot, eliminated);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Fri Feb 27 16:36:38 2015 +0100
@@ -26,12 +26,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 
 /**
- * Extends {@link LIRFrameState} to handle {@link HotSpotMonitorValue}s correctly.
+ * Extends {@link LIRFrameState} to handle {@link StackLockValue}s correctly.
  */
 class HotSpotLIRFrameState extends LIRFrameState {
 
@@ -41,8 +40,8 @@
 
     @Override
     protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) {
-        if (value instanceof HotSpotMonitorValue) {
-            HotSpotMonitorValue monitor = (HotSpotMonitorValue) value;
+        if (value instanceof StackLockValue) {
+            StackLockValue monitor = (StackLockValue) value;
             if (monitor.getOwner() instanceof Value) {
                 Value owner = (Value) monitor.getOwner();
                 if (processed(owner)) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMonitorValue.java	Fri Feb 27 16:35:54 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2011, 2014, 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.hotspot.meta;
-
-import static com.oracle.graal.api.code.ValueUtil.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-
-/**
- * Represents lock information in the debug information.
- */
-public final class HotSpotMonitorValue extends AbstractValue implements JavaValue {
-
-    private static final long serialVersionUID = 8241681800464483691L;
-
-    private JavaValue owner;
-    private StackSlotValue slot;
-    private final boolean eliminated;
-
-    public HotSpotMonitorValue(JavaValue owner, StackSlotValue slot, boolean eliminated) {
-        super(LIRKind.Illegal);
-        this.owner = owner;
-        this.slot = slot;
-        this.eliminated = eliminated;
-    }
-
-    public JavaValue getOwner() {
-        return owner;
-    }
-
-    public void setOwner(JavaValue newOwner) {
-        this.owner = newOwner;
-    }
-
-    public Value getSlot() {
-        return slot;
-    }
-
-    public boolean isEliminated() {
-        return eliminated;
-    }
-
-    @Override
-    public String toString() {
-        return "monitor[" + owner + (slot != null ? ", " + slot : "") + (eliminated ? ", eliminated" : "") + "]";
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 43;
-        int result = super.hashCode();
-        result = prime * result + (eliminated ? 1231 : 1237);
-        result = prime * result + owner.hashCode();
-        result = prime * result + slot.hashCode();
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof HotSpotMonitorValue) {
-            HotSpotMonitorValue other = (HotSpotMonitorValue) obj;
-            return super.equals(obj) && eliminated == other.eliminated && owner.equals(other.owner) && slot.equals(other.slot);
-        }
-        return false;
-    }
-
-    public void setSlot(StackSlotValue stackSlot) {
-        assert slot == null || (isVirtualStackSlot(slot) && (slot.equals(stackSlot) || isStackSlot(stackSlot))) : String.format("Can not set slot for %s to %s", this, stackSlot);
-        slot = stackSlot;
-    }
-}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java	Fri Feb 27 16:36:38 2015 +0100
@@ -195,14 +195,13 @@
                     }
                 };
 
-                ValuePositionProcedure useProcedure = (instruction, position) -> {
-                    Value value = position.get(instruction);
+                InstructionValueConsumer useConsumer = (instruction, value, mode, flags) -> {
                     if (isVariable(value)) {
                         Variable var = (Variable) value;
                         if (!phiConstants.get(var.index)) {
                             DefUseTree tree = map.get(var);
                             if (tree != null) {
-                                tree.addUsage(block, instruction, position);
+                                tree.addUsage(block, instruction, value);
                                 Debug.log("usage of %s : %s", var, instruction);
                             }
                         }
@@ -214,8 +213,8 @@
                     // set instruction id to the index in the lir instruction list
                     inst.setId(opId++);
                     inst.visitEachOutput(loadConsumer);
-                    inst.forEachInputPos(useProcedure);
-                    inst.forEachAlivePos(useProcedure);
+                    inst.forEachInput(useConsumer);
+                    inst.forEachAlive(useConsumer);
 
                 }
             }
@@ -297,7 +296,7 @@
             Debug.log("new move (%s) and inserted in block %s", move, block);
             // update usages
             for (UseEntry u : usages) {
-                u.getPosition().set(u.getInstruction(), variable);
+                u.setValue(variable);
                 Debug.log("patched instruction %s", u.getInstruction());
             }
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/DefUseTree.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/DefUseTree.java	Fri Feb 27 16:36:38 2015 +0100
@@ -66,8 +66,8 @@
         return "DefUseTree [" + instruction + "|" + block + "," + uses + "]";
     }
 
-    public void addUsage(AbstractBlockBase<?> b, LIRInstruction inst, ValuePosition position) {
-        uses.add(new UseEntry(b, inst, position));
+    public void addUsage(AbstractBlockBase<?> b, LIRInstruction inst, Value value) {
+        uses.add(new UseEntry(b, inst, value));
     }
 
     public int usageCount() {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/UseEntry.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/UseEntry.java	Fri Feb 27 16:36:38 2015 +0100
@@ -33,12 +33,12 @@
 
     private final AbstractBlockBase<?> block;
     private final LIRInstruction instruction;
-    private final ValuePosition position;
+    private final Value value;
 
-    public UseEntry(AbstractBlockBase<?> block, LIRInstruction instruction, ValuePosition position) {
+    public UseEntry(AbstractBlockBase<?> block, LIRInstruction instruction, Value value) {
         this.block = block;
         this.instruction = instruction;
-        this.position = position;
+        this.value = value;
     }
 
     public LIRInstruction getInstruction() {
@@ -49,16 +49,26 @@
         return block;
     }
 
-    public ValuePosition getPosition() {
-        return position;
+    public void setValue(Value newValue) {
+        replaceValue(instruction, value, newValue);
+    }
+
+    private static void replaceValue(LIRInstruction op, Value oldValue, Value newValue) {
+        ValueProcedure proc = (value, mode, flags) -> value.identityEquals(oldValue) ? newValue : value;
+        op.forEachAlive(proc);
+        op.forEachInput(proc);
+        op.forEachOutput(proc);
+        op.forEachTemp(proc);
+        op.forEachState(proc);
     }
 
     public Value getValue() {
-        return position.get(instruction);
+        return value;
     }
 
     @Override
     public String toString() {
         return "Use[" + getValue() + ":" + instruction + ":" + block + "]";
     }
+
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/LIRPhase.java	Fri Feb 27 16:36:38 2015 +0100
@@ -78,10 +78,12 @@
     }
 
     public final <B extends AbstractBlockBase<B>> void apply(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, C context, boolean dumpLIR) {
-        try (TimerCloseable a = timer.start(); Scope s = Debug.scope(getName(), this); Closeable c = memUseTracker.start()) {
-            run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context);
-            if (dumpLIR && Debug.isDumpEnabled(PHASE_DUMP_LEVEL)) {
-                Debug.dump(PHASE_DUMP_LEVEL, lirGenRes.getLIR(), "After phase %s", getName());
+        try (Scope s = Debug.scope(getName(), this)) {
+            try (TimerCloseable a = timer.start(); Closeable c = memUseTracker.start()) {
+                run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context);
+                if (dumpLIR && Debug.isDumpEnabled(PHASE_DUMP_LEVEL)) {
+                    Debug.dump(PHASE_DUMP_LEVEL, lirGenRes.getLIR(), "After phase %s", getName());
+                }
             }
         } catch (Throwable e) {
             throw Debug.handle(e);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -64,10 +64,11 @@
      * inputs by increasing {@link Node#id} and call {@link Graph#findDuplicate(Node)} on the node
      * if it's currently in a graph.
      *
-     * @return the original node or another node with the same input ordering
+     * @return the original node or another node with the same inputs, ignoring ordering.
      */
     @SuppressWarnings("deprecation")
     public LogicNode maybeCommuteInputs() {
+        assert this instanceof BinaryCommutative;
         if (x.getId() > y.getId()) {
             ValueNode tmp = x;
             x = y;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -27,6 +27,7 @@
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp;
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Add;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -34,7 +35,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "+")
-public class AddNode extends BinaryArithmeticNode<Add> implements NarrowableArithmeticNode {
+public class AddNode extends BinaryArithmeticNode<Add> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> {
 
     public static final NodeClass<AddNode> TYPE = NodeClass.create(AddNode.class);
 
@@ -103,7 +104,7 @@
         } else if (forY instanceof NegateNode) {
             return BinaryArithmeticNode.sub(forX, ((NegateNode) forY).getValue());
         }
-        return this.maybeCommuteInputs();
+        return this;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -25,9 +25,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.*;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.And;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -36,7 +37,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "&")
-public final class AndNode extends BinaryArithmeticNode<And> implements NarrowableArithmeticNode {
+public final class AndNode extends BinaryArithmeticNode<And> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> {
 
     public static final NodeClass<AndNode> TYPE = NodeClass.create(AndNode.class);
 
@@ -95,7 +96,7 @@
 
             return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
-        return this.maybeCommuteInputs();
+        return this;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -37,7 +37,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public abstract class BinaryArithmeticNode<OP> extends BinaryNode implements ArithmeticLIRLowerable {
+public abstract class BinaryArithmeticNode<OP> extends BinaryNode implements ArithmeticLIRLowerable, Canonicalizable.Binary<ValueNode> {
 
     @SuppressWarnings("rawtypes") public static final NodeClass<BinaryArithmeticNode> TYPE = NodeClass.create(BinaryArithmeticNode.class);
 
@@ -252,4 +252,30 @@
         }
         return false;
     }
+
+    /**
+     * Ensure a canonical ordering of inputs for commutative nodes to improve GVN results. Order the
+     * inputs by increasing {@link Node#id} and call {@link Graph#findDuplicate(Node)} on the node
+     * if it's currently in a graph. It's assumed that if there was a constant on the left it's been
+     * moved to the right by other code and that ordering is left alone.
+     *
+     * @return the original node or another node with the same input ordering
+     */
+    @SuppressWarnings("deprecation")
+    public BinaryNode maybeCommuteInputs() {
+        assert this instanceof BinaryCommutative;
+        if (!y.isConstant() && x.getId() > y.getId()) {
+            ValueNode tmp = x;
+            x = y;
+            y = tmp;
+            if (graph() != null) {
+                // See if this node already exists
+                BinaryNode duplicate = graph().findDuplicate(this);
+                if (duplicate != null) {
+                    return duplicate;
+                }
+            }
+        }
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -68,29 +68,4 @@
         this.x = x;
         this.y = y;
     }
-
-    /**
-     * Ensure a canonical ordering of inputs for commutative nodes to improve GVN results. Order the
-     * inputs by increasing {@link Node#id} and call {@link Graph#findDuplicate(Node)} on the node
-     * if it's currently in a graph. It's assumed that if there was a constant on the left it's been
-     * moved to the right by other code and that ordering is left alone.
-     *
-     * @return the original node or another node with the same input ordering
-     */
-    @SuppressWarnings("deprecation")
-    public BinaryNode maybeCommuteInputs() {
-        if (!y.isConstant() && x.getId() > y.getId()) {
-            ValueNode tmp = x;
-            x = y;
-            y = tmp;
-            if (graph() != null) {
-                // See if this node already exists
-                BinaryNode duplicate = graph().findDuplicate(this);
-                if (duplicate != null) {
-                    return duplicate;
-                }
-            }
-        }
-        return this;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -38,7 +38,7 @@
  * into variants that do not materialize the value (CompareIf, CompareGuard...)
  */
 @NodeInfo
-public abstract class CompareNode extends BinaryOpLogicNode {
+public abstract class CompareNode extends BinaryOpLogicNode implements Canonicalizable.Binary<ValueNode> {
 
     public static final NodeClass<CompareNode> TYPE = NodeClass.create(CompareNode.class);
     protected final Condition condition;
@@ -125,9 +125,6 @@
                 return duplicateModified(convertX.getValue(), convertY.getValue());
             }
         }
-        if (condition.isCommutative()) {
-            return this.maybeCommuteInputs();
-        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -27,13 +27,14 @@
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
-public final class FloatEqualsNode extends CompareNode {
+public final class FloatEqualsNode extends CompareNode implements BinaryCommutative<ValueNode> {
     public static final NodeClass<FloatEqualsNode> TYPE = NodeClass.create(FloatEqualsNode.class);
 
     public FloatEqualsNode(ValueNode x, ValueNode y) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -27,13 +27,14 @@
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
-public final class IntegerEqualsNode extends CompareNode {
+public final class IntegerEqualsNode extends CompareNode implements BinaryCommutative<ValueNode> {
     public static final NodeClass<IntegerEqualsNode> TYPE = NodeClass.create(IntegerEqualsNode.class);
 
     public IntegerEqualsNode(ValueNode x, ValueNode y) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
@@ -34,7 +35,7 @@
  * both x and y.
  */
 @NodeInfo
-public final class IntegerTestNode extends BinaryOpLogicNode {
+public final class IntegerTestNode extends BinaryOpLogicNode implements BinaryCommutative<ValueNode> {
     public static final NodeClass<IntegerTestNode> TYPE = NodeClass.create(IntegerTestNode.class);
 
     public IntegerTestNode(ValueNode x, ValueNode y) {
@@ -55,6 +56,6 @@
                 return LogicConstantNode.contradiction();
             }
         }
-        return this.maybeCommuteInputs();
+        return this;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -26,8 +26,9 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Mul;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -35,7 +36,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "*")
-public class MulNode extends BinaryArithmeticNode<Mul> implements NarrowableArithmeticNode {
+public class MulNode extends BinaryArithmeticNode<Mul> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> {
 
     public static final NodeClass<MulNode> TYPE = NodeClass.create(MulNode.class);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -25,9 +25,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.*;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Or;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -36,7 +37,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "|")
-public final class OrNode extends BinaryArithmeticNode<Or> {
+public final class OrNode extends BinaryArithmeticNode<Or> implements BinaryCommutative<ValueNode> {
 
     public static final NodeClass<OrNode> TYPE = NodeClass.create(OrNode.class);
 
@@ -83,7 +84,7 @@
             }
             return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
-        return this.maybeCommuteInputs();
+        return this;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/PointerEqualsNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/PointerEqualsNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -25,13 +25,14 @@
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
-public class PointerEqualsNode extends CompareNode {
+public class PointerEqualsNode extends CompareNode implements BinaryCommutative<ValueNode> {
 
     public static final NodeClass<PointerEqualsNode> TYPE = NodeClass.create(PointerEqualsNode.class);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -25,9 +25,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.*;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Xor;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -36,7 +37,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "^")
-public final class XorNode extends BinaryArithmeticNode<Xor> {
+public final class XorNode extends BinaryArithmeticNode<Xor> implements BinaryCommutative<ValueNode> {
 
     public static final NodeClass<XorNode> TYPE = NodeClass.create(XorNode.class);
 
@@ -84,7 +85,7 @@
             }
             return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
-        return this.maybeCommuteInputs();
+        return this;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java	Fri Feb 27 16:36:38 2015 +0100
@@ -32,14 +32,10 @@
 
     LocationIdentity getLocationIdentity();
 
-    default MemoryNode getLastLocationAccess() {
-        return null;
-    }
+    MemoryNode getLastLocationAccess();
 
     /**
      * @param lla the {@link MemoryNode} that represents the last kill of the location
      */
-    default void setLastLocationAccess(MemoryNode lla) {
-        // empty
-    }
+    void setLastLocationAccess(MemoryNode lla);
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Fri Feb 27 16:36:38 2015 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.graph.Graph.NodeEventListener;
 import com.oracle.graal.graph.Graph.NodeEventScope;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -261,6 +262,9 @@
                     Node canonical;
                     try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) {
                         canonical = ((Canonicalizable) node).canonical(tool);
+                        if (canonical == node && nodeClass.isCommutative()) {
+                            canonical = ((BinaryCommutative<?>) node).maybeCommuteInputs();
+                        }
                     }
                     if (performReplacement(node, canonical)) {
                         return true;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Fri Feb 27 16:36:38 2015 +0100
@@ -251,7 +251,9 @@
 
                 @Override
                 protected NodeBitMap getInitialState() {
-                    return graph.createNodeBitMap();
+                    NodeBitMap ret = graph.createNodeBitMap();
+                    ret.markAll(graph.getNodes().filter(ConstantNode.class));
+                    return ret;
                 }
 
                 @Override
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ArrayEqualsNode.java	Fri Feb 27 16:36:38 2015 +0100
@@ -51,6 +51,8 @@
     /** Length of both arrays. */
     @Input ValueNode length;
 
+    @OptionalInput(InputType.Memory) MemoryNode lastLocationAccess;
+
     public ArrayEqualsNode(ValueNode array1, ValueNode array2, ValueNode length) {
         super(TYPE, StampFactory.forKind(Kind.Boolean));
         // Ignore nullness in stamp equality test
@@ -139,4 +141,13 @@
     public LocationIdentity getLocationIdentity() {
         return NamedLocationIdentity.getArrayLocation(kind);
     }
+
+    public MemoryNode getLastLocationAccess() {
+        return lastLocationAccess;
+    }
+
+    public void setLastLocationAccess(MemoryNode lla) {
+        updateUsages(ValueNodeUtil.asNode(lastLocationAccess), ValueNodeUtil.asNode(lla));
+        lastLocationAccess = lla;
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Fri Feb 27 16:36:38 2015 +0100
@@ -86,42 +86,38 @@
 
     public static void registerExactMathPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
         Registration r = new Registration(plugins, metaAccess, ExactMath.class);
-        r.register2("addExact", Integer.TYPE, Integer.TYPE, new InvocationPlugin() {
-            public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
-                builder.push(Kind.Int.getStackKind(), builder.append(new IntegerAddExactNode(x, y)));
-                return true;
-            }
-        });
-        r.register2("addExact", Long.TYPE, Long.TYPE, new InvocationPlugin() {
-            public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
-                builder.push(Kind.Long, builder.append(new IntegerAddExactNode(x, y)));
-                return true;
-            }
-        });
-        r.register2("subtractExact", Integer.TYPE, Integer.TYPE, new InvocationPlugin() {
-            public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
-                builder.push(Kind.Int.getStackKind(), builder.append(new IntegerSubExactNode(x, y)));
-                return true;
-            }
-        });
-        r.register2("subtractExact", Long.TYPE, Long.TYPE, new InvocationPlugin() {
-            public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
-                builder.push(Kind.Long, builder.append(new IntegerSubExactNode(x, y)));
-                return true;
-            }
-        });
-        r.register2("multiplyExact", Integer.TYPE, Integer.TYPE, new InvocationPlugin() {
-            public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
-                builder.push(Kind.Int.getStackKind(), builder.append(new IntegerMulExactNode(x, y)));
-                return true;
-            }
-        });
-        r.register2("multiplyExact", Long.TYPE, Long.TYPE, new InvocationPlugin() {
-            public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
-                builder.push(Kind.Long, builder.append(new IntegerMulExactNode(x, y)));
-                return true;
-            }
-        });
+        for (Kind kind : new Kind[]{Kind.Int, Kind.Long}) {
+            r.register2("addExact", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() {
+                public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
+                    builder.push(kind.getStackKind(), builder.append(new IntegerAddExactNode(x, y)));
+                    return true;
+                }
+            });
+            r.register2("subtractExact", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() {
+                public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
+                    builder.push(kind.getStackKind(), builder.append(new IntegerSubExactNode(x, y)));
+                    return true;
+                }
+            });
+            r.register2("multiplyExact", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() {
+                public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
+                    builder.push(kind.getStackKind(), builder.append(new IntegerMulExactNode(x, y)));
+                    return true;
+                }
+            });
+            r.register2("multiplyHigh", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() {
+                public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
+                    builder.push(kind.getStackKind(), builder.append(new IntegerMulHighNode(x, y)));
+                    return true;
+                }
+            });
+            r.register2("multiplyHighUnsigned", kind.toJavaClass(), kind.toJavaClass(), new InvocationPlugin() {
+                public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) {
+                    builder.push(kind.getStackKind(), builder.append(new UnsignedMulHighNode(x, y)));
+                    return true;
+                }
+            });
+        }
     }
 
     public static void registerCompilerDirectivesPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java	Fri Feb 27 16:36:38 2015 +0100
@@ -41,7 +41,6 @@
 public abstract class Node implements NodeInterface, Cloneable {
 
     @CompilationFinal private Node parent;
-
     @CompilationFinal private SourceSection sourceSection;
 
     /**
@@ -573,11 +572,7 @@
 
     public final void atomic(Runnable closure) {
         RootNode rootNode = getRootNode();
-        if (rootNode != null) {
-            synchronized (rootNode) {
-                closure.run();
-            }
-        } else {
+        synchronized (rootNode != null ? rootNode : GIL) {
             closure.run();
         }
     }
@@ -585,14 +580,10 @@
     public final <T> T atomic(Callable<T> closure) {
         try {
             RootNode rootNode = getRootNode();
-            if (rootNode != null) {
-                synchronized (rootNode) {
-                    return closure.call();
-                }
-            } else {
+            synchronized (rootNode != null ? rootNode : GIL) {
                 return closure.call();
             }
-        } catch (RuntimeException e) {
+        } catch (RuntimeException | Error e) {
             throw e;
         } catch (Exception e) {
             throw new RuntimeException(e);
@@ -625,4 +616,6 @@
         }
         return "";
     }
+
+    private static final Object GIL = new Object();
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Fri Feb 27 16:36:38 2015 +0100
@@ -696,6 +696,42 @@
         return false;
     }
 
+    /**
+     * Executes a closure for every non-null child of the parent node.
+     *
+     * @return {@code true} if all children were visited, {@code false} otherwise
+     */
+    public static boolean forEachChild(Node parent, NodeVisitor visitor) {
+        Objects.requireNonNull(visitor);
+        NodeClass parentNodeClass = NodeClass.get(parent.getClass());
+
+        for (NodeField field : parentNodeClass.getChildFields()) {
+            Object child = field.getObject(parent);
+            if (child != null) {
+                if (!visitor.visit((Node) child)) {
+                    return false;
+                }
+            }
+        }
+
+        for (NodeField field : parentNodeClass.getChildrenFields()) {
+            Object arrayObject = field.getObject(parent);
+            if (arrayObject != null) {
+                Object[] array = (Object[]) arrayObject;
+                for (int i = 0; i < array.length; i++) {
+                    Object child = array[i];
+                    if (child != null) {
+                        if (!visitor.visit((Node) child)) {
+                            return false;
+                        }
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
     /** Returns all declared fields in the class hierarchy. */
     private static Field[] getAllFields(Class<? extends Object> clazz) {
         Field[] declaredFields = clazz.getDeclaredFields();
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java	Fri Feb 27 16:36:38 2015 +0100
@@ -27,13 +27,11 @@
 import java.io.*;
 import java.util.*;
 import java.util.Map.Entry;
-import java.util.concurrent.atomic.*;
 
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.instrument.impl.*;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.Node.Child;
 import com.oracle.truffle.api.source.*;
 
 /**
@@ -160,7 +158,7 @@
                 curSource = source;
                 curLineTable = new Long[source.getLineCount()];
             }
-            curLineTable[lineNo - 1] = entry.getValue().count.longValue();
+            curLineTable[lineNo - 1] = entry.getValue().count;
         }
         if (curSource != null) {
             result.put(curSource, curLineTable);
@@ -206,7 +204,7 @@
             while (curLineNo < lineNo) {
                 displayLine(out, null, curSource, curLineNo++);
             }
-            displayLine(out, entry.getValue().count, curSource, curLineNo++);
+            displayLine(out, entry.getValue(), curSource, curLineNo++);
         }
         if (curSource != null) {
             while (curLineNo <= curSource.getLineCount()) {
@@ -215,11 +213,11 @@
         }
     }
 
-    private static void displayLine(PrintStream out, AtomicLong value, Source source, int lineNo) {
-        if (value == null) {
+    private static void displayLine(PrintStream out, CoverageRecord record, Source source, int lineNo) {
+        if (record == null) {
             out.format("%14s", " ");
         } else {
-            out.format("(%12d)", value.longValue());
+            out.format("(%12d)", record.count);
         }
         out.format(" %3d: ", lineNo);
         out.println(source.getCode(lineNo));
@@ -227,33 +225,25 @@
 
     /**
      * A listener for events at each instrumented AST location. This listener counts
-     * "execution calls" to the instrumented node and is <em>stateful</em>. State in listeners must
-     * be considered carefully since ASTs, along with all instrumentation (including event listener
-     * such as this) are routinely cloned by the Truffle runtime. AST cloning is <em>shallow</em>
-     * (for non- {@link Child} nodes), so in this case the actual count <em>is shared</em> among all
-     * the clones; the count is also held in a table indexed by source line.
-     * <p>
-     * In contrast, a primitive field would <em>not</em> be shared among clones and resulting counts
-     * would not be accurate.
+     * "execution calls" to the instrumented node.
      */
-    private final class CoverageEventListener extends DefaultEventListener {
+    private final class CoverageRecord extends DefaultEventListener {
 
-        /**
-         * Shared by all clones of the associated instrument and by the table of counters for the
-         * line.
-         */
-        private final AtomicLong count;
+        private final SourceSection srcSection; // The text of the code being counted
+        private Instrument instrument;  // The attached Instrument, in case need to remove.
+        private long count = 0;
 
-        CoverageEventListener(AtomicLong count) {
-            this.count = count;
+        CoverageRecord(SourceSection srcSection) {
+            this.srcSection = srcSection;
         }
 
         @Override
         public void enter(Node node, VirtualFrame vFrame) {
             if (isEnabled()) {
-                count.getAndIncrement();
+                count++;
             }
         }
+
     }
 
     private static final class LineLocationEntryComparator implements Comparator<Entry<LineLocation, CoverageRecord>> {
@@ -282,35 +272,23 @@
                     if (record != null) {
                         // Another node starts on same line; count only the first (textually)
                         if (srcSection.getCharIndex() > record.srcSection.getCharIndex()) {
-                            // Record already in place, corresponds to code earlier on line
+                            // Existing record, corresponds to code earlier on line
                             return;
                         } else {
-                            // Record already in place, corresponds to later code; replace it
+                            // Existing record, corresponds to code at a later position; replace it
                             record.instrument.dispose();
                         }
                     }
-                    final AtomicLong count = new AtomicLong();
-                    final CoverageEventListener eventListener = new CoverageEventListener(count);
-                    final Instrument instrument = Instrument.create(eventListener, CoverageTracker.class.getSimpleName());
+
+                    final CoverageRecord coverage = new CoverageRecord(srcSection);
+                    final Instrument instrument = Instrument.create(coverage, CoverageTracker.class.getSimpleName());
+                    coverage.instrument = instrument;
                     instruments.add(instrument);
                     probe.attach(instrument);
-                    coverageMap.put(lineLocation, new CoverageRecord(srcSection, instrument, count));
+                    coverageMap.put(lineLocation, coverage);
                 }
             }
         }
     }
 
-    private class CoverageRecord {
-
-        final SourceSection srcSection; // The text of the code being counted
-        final Instrument instrument;  // The attached Instrument, in case need to remove.
-        final AtomicLong count;
-
-        CoverageRecord(SourceSection srcSection, Instrument instrument, AtomicLong count) {
-            this.srcSection = srcSection;
-            this.instrument = instrument;
-            this.count = count;
-        }
-    }
-
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/PrimitiveValueProfile.java	Fri Feb 27 16:36:38 2015 +0100
@@ -51,25 +51,26 @@
     @SuppressWarnings("unchecked")
     @Override
     public Object profile(Object value) {
-        if (cachedValue != GENERIC) {
-            if (cachedValue instanceof Byte && value instanceof Byte && (byte) cachedValue == (byte) value) {
-                return cachedValue;
-            } else if (cachedValue instanceof Short && value instanceof Short && (short) cachedValue == (short) value) {
-                return cachedValue;
-            } else if (cachedValue instanceof Integer && value instanceof Integer && (int) cachedValue == (int) value) {
-                return cachedValue;
-            } else if (cachedValue instanceof Long && value instanceof Long && (long) cachedValue == (long) value) {
-                return cachedValue;
-            } else if (cachedValue instanceof Float && value instanceof Float && exactCompare((float) cachedValue, (float) value)) {
-                return cachedValue;
-            } else if (cachedValue instanceof Double && value instanceof Double && exactCompare((double) cachedValue, (double) value)) {
-                return cachedValue;
-            } else if (cachedValue instanceof Boolean && value instanceof Boolean && (boolean) cachedValue == (boolean) value) {
-                return cachedValue;
-            } else if (cachedValue instanceof Character && value instanceof Character && (char) cachedValue == (char) value) {
-                return cachedValue;
-            } else if (cachedValue == value) {
-                return cachedValue;
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Byte && value instanceof Byte && (byte) snapshot == (byte) value) {
+                return snapshot;
+            } else if (snapshot instanceof Short && value instanceof Short && (short) snapshot == (short) value) {
+                return snapshot;
+            } else if (snapshot instanceof Integer && value instanceof Integer && (int) snapshot == (int) value) {
+                return snapshot;
+            } else if (snapshot instanceof Long && value instanceof Long && (long) snapshot == (long) value) {
+                return snapshot;
+            } else if (snapshot instanceof Float && value instanceof Float && exactCompare((float) snapshot, (float) value)) {
+                return snapshot;
+            } else if (snapshot instanceof Double && value instanceof Double && exactCompare((double) snapshot, (double) value)) {
+                return snapshot;
+            } else if (snapshot instanceof Boolean && value instanceof Boolean && (boolean) snapshot == (boolean) value) {
+                return snapshot;
+            } else if (snapshot instanceof Character && value instanceof Character && (char) snapshot == (char) value) {
+                return snapshot;
+            } else if (snapshot == value) {
+                return snapshot;
             } else {
                 cacheMiss(value);
             }
@@ -78,9 +79,10 @@
     }
 
     public byte profile(byte value) {
-        if (cachedValue != GENERIC) {
-            if (cachedValue instanceof Byte && (byte) cachedValue == value) {
-                return (byte) cachedValue;
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Byte && (byte) snapshot == value) {
+                return (byte) snapshot;
             } else {
                 cacheMiss(value);
             }
@@ -89,9 +91,10 @@
     }
 
     public short profile(short value) {
-        if (cachedValue != GENERIC) {
-            if (cachedValue instanceof Short && (short) cachedValue == value) {
-                return (short) cachedValue;
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Short && (short) snapshot == value) {
+                return (short) snapshot;
             } else {
                 cacheMiss(value);
             }
@@ -100,9 +103,10 @@
     }
 
     public int profile(int value) {
-        if (cachedValue != GENERIC) {
-            if (cachedValue instanceof Integer && (int) cachedValue == value) {
-                return (int) cachedValue;
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Integer && (int) snapshot == value) {
+                return (int) snapshot;
             } else {
                 cacheMiss(value);
             }
@@ -111,9 +115,10 @@
     }
 
     public long profile(long value) {
-        if (cachedValue != GENERIC) {
-            if (cachedValue instanceof Long && (long) cachedValue == value) {
-                return (long) cachedValue;
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Long && (long) snapshot == value) {
+                return (long) snapshot;
             } else {
                 cacheMiss(value);
             }
@@ -122,9 +127,10 @@
     }
 
     public float profile(float value) {
-        if (cachedValue != GENERIC) {
-            if (cachedValue instanceof Float && exactCompare((float) cachedValue, value)) {
-                return (float) cachedValue;
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Float && exactCompare((float) snapshot, value)) {
+                return (float) snapshot;
             } else {
                 cacheMiss(value);
             }
@@ -133,9 +139,10 @@
     }
 
     public double profile(double value) {
-        if (cachedValue != GENERIC) {
-            if (cachedValue instanceof Double && exactCompare((double) cachedValue, value)) {
-                return (double) cachedValue;
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Double && exactCompare((double) snapshot, value)) {
+                return (double) snapshot;
             } else {
                 cacheMiss(value);
             }
@@ -144,9 +151,10 @@
     }
 
     public boolean profile(boolean value) {
-        if (cachedValue != GENERIC) {
-            if (cachedValue instanceof Boolean && (boolean) cachedValue == value) {
-                return (boolean) cachedValue;
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Boolean && (boolean) snapshot == value) {
+                return (boolean) snapshot;
             } else {
                 cacheMiss(value);
             }
@@ -155,9 +163,10 @@
     }
 
     public char profile(char value) {
-        if (cachedValue != GENERIC) {
-            if (cachedValue instanceof Character && (char) cachedValue == value) {
-                return (char) cachedValue;
+        Object snapshot = this.cachedValue;
+        if (snapshot != GENERIC) {
+            if (snapshot instanceof Character && (char) snapshot == value) {
+                return (char) snapshot;
             } else {
                 cacheMiss(value);
             }
@@ -183,6 +192,7 @@
     }
 
     private void cacheMiss(Object value) {
+        // TODO should we try to handle this more atomically?
         CompilerDirectives.transferToInterpreterAndInvalidate();
         if (cachedValue == UNINITIALIZED) {
             cachedValue = value;
@@ -208,17 +218,18 @@
     }
 
     private String formatValue() {
-        if (cachedValue == null) {
+        Object snapshot = this.cachedValue;
+        if (snapshot == null) {
             return "null";
-        } else if (cachedValue == UNINITIALIZED) {
+        } else if (snapshot == UNINITIALIZED) {
             return "uninitialized";
-        } else if (cachedValue == GENERIC) {
+        } else if (snapshot == GENERIC) {
             return "generic";
-        } else if (cachedValue instanceof Byte || cachedValue instanceof Short || cachedValue instanceof Integer || cachedValue instanceof Long || cachedValue instanceof Float ||
-                        cachedValue instanceof Double || cachedValue instanceof Boolean || cachedValue instanceof Character) {
-            return String.format("%s=%s", cachedValue.getClass().getSimpleName(), cachedValue);
+        } else if (snapshot instanceof Byte || snapshot instanceof Short || snapshot instanceof Integer || snapshot instanceof Long || snapshot instanceof Float || snapshot instanceof Double ||
+                        snapshot instanceof Boolean || snapshot instanceof Character) {
+            return String.format("%s=%s", snapshot.getClass().getSimpleName(), snapshot);
         } else {
-            return String.format("%s@%x", cachedValue.getClass().getSimpleName(), Objects.hash(cachedValue));
+            return String.format("%s@%x", snapshot.getClass().getSimpleName(), Objects.hash(snapshot));
         }
     }
 }
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java	Fri Feb 27 16:35:54 2015 +0100
+++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java	Fri Feb 27 16:36:38 2015 +0100
@@ -353,9 +353,8 @@
      */
     private ShapeImpl addPropertyInternal(Property prop) {
         CompilerAsserts.neverPartOfCompilation();
-        assert prop.isShadow() || !(this.hasProperty(prop.getKey())) : "duplicate property";
+        assert prop.isShadow() || !(this.hasProperty(prop.getKey())) : "duplicate property " + prop.getKey();
         assert !getPropertyListInternal(false).contains(prop);
-        // invalidatePropertyAssumption(prop.getName());
 
         AddPropertyTransition addTransition = new AddPropertyTransition(prop);
         ShapeImpl cachedShape = queryTransition(addTransition);
@@ -653,7 +652,7 @@
                 newShape = newShape.applyTransition(previous, true);
             }
 
-            getTransitionMapForWrite().put(transition, newShape);
+            addIndirectTransition(transition, newShape);
             return newShape;
         } else {
             return null;
@@ -899,7 +898,7 @@
     private Property[] createPropertiesArray() {
         propertyListAllocCount.inc();
         Property[] propertiesArray = new Property[getPropertyCount()];
-        List<Property> ownProperties = getPropertyList(ALL);
+        List<Property> ownProperties = getPropertyList();
         assert ownProperties.size() == getPropertyCount();
         for (int i = 0; i < getPropertyCount(); i++) {
             propertiesArray[i] = ownProperties.get(i);
@@ -1099,7 +1098,7 @@
     /**
      * Match all filter.
      */
-    public static final Pred<Property> ALL = new Pred<Property>() {
+    private static final Pred<Property> ALL = new Pred<Property>() {
         public boolean test(Property t) {
             return true;
         }
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Feb 27 16:35:54 2015 +0100
+++ b/src/share/vm/classfile/systemDictionary.hpp	Fri Feb 27 16:36:38 2015 +0100
@@ -198,7 +198,6 @@
   GRAAL_ONLY(do_klass(HotSpotNmethod_klass,                  com_oracle_graal_hotspot_meta_HotSpotNmethod,                 Graal)) \
   GRAAL_ONLY(do_klass(HotSpotResolvedJavaMethodImpl_klass,   com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethodImpl,  Graal)) \
   GRAAL_ONLY(do_klass(HotSpotResolvedObjectTypeImpl_klass,   com_oracle_graal_hotspot_meta_HotSpotResolvedObjectTypeImpl,  Graal)) \
-  GRAAL_ONLY(do_klass(HotSpotMonitorValue_klass,             com_oracle_graal_hotspot_meta_HotSpotMonitorValue,            Graal)) \
   GRAAL_ONLY(do_klass(HotSpotCompressedNullConstant_klass,   com_oracle_graal_hotspot_meta_HotSpotCompressedNullConstant,  Graal)) \
   GRAAL_ONLY(do_klass(HotSpotObjectConstantImpl_klass,       com_oracle_graal_hotspot_meta_HotSpotObjectConstantImpl,      Graal)) \
   GRAAL_ONLY(do_klass(HotSpotMetaspaceConstantImpl_klass,    com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstantImpl,   Graal)) \
@@ -227,6 +226,7 @@
   GRAAL_ONLY(do_klass(RegisterValue_klass,                   com_oracle_graal_api_code_RegisterValue,                      Graal)) \
   GRAAL_ONLY(do_klass(RegisterCategory_klass,                com_oracle_graal_api_code_Register_RegisterCategory,          Graal)) \
   GRAAL_ONLY(do_klass(StackSlot_klass,                       com_oracle_graal_api_code_StackSlot,                          Graal)) \
+  GRAAL_ONLY(do_klass(StackLockValue_klass,                  com_oracle_graal_api_code_StackLockValue,                     Graal)) \
   GRAAL_ONLY(do_klass(VirtualObject_klass,                   com_oracle_graal_api_code_VirtualObject,                      Graal)) \
   GRAAL_ONLY(do_klass(SpeculationLog_klass,                  com_oracle_graal_api_code_SpeculationLog,                     Graal)) \
   GRAAL_ONLY(do_klass(JavaConstant_klass,                    com_oracle_graal_api_meta_JavaConstant,                       Graal)) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Feb 27 16:35:54 2015 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Feb 27 16:36:38 2015 +0100
@@ -305,7 +305,6 @@
   GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotNmethod,             "com/oracle/graal/hotspot/meta/HotSpotNmethod"))                  \
   GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotResolvedJavaMethodImpl, "com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl")) \
   GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotResolvedObjectTypeImpl, "com/oracle/graal/hotspot/meta/HotSpotResolvedObjectTypeImpl")) \
-  GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue,        "com/oracle/graal/hotspot/meta/HotSpotMonitorValue"))             \
   GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotCompressedNullConstant, "com/oracle/graal/hotspot/meta/HotSpotCompressedNullConstant")) \
   GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotObjectConstantImpl,  "com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl"))       \
   GRAAL_ONLY(template(com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstantImpl,"com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstantImpl"))   \
@@ -343,6 +342,7 @@
   GRAAL_ONLY(template(com_oracle_graal_api_code_RegisterValue,                  "com/oracle/graal/api/code/RegisterValue"))                       \
   GRAAL_ONLY(template(com_oracle_graal_api_code_Register_RegisterCategory,      "com/oracle/graal/api/code/Register$RegisterCategory"))           \
   GRAAL_ONLY(template(com_oracle_graal_api_code_StackSlot,                      "com/oracle/graal/api/code/StackSlot"))                           \
+  GRAAL_ONLY(template(com_oracle_graal_api_code_StackLockValue,                 "com/oracle/graal/api/code/StackLockValue"))                      \
   GRAAL_ONLY(template(com_oracle_graal_api_code_VirtualObject,                  "com/oracle/graal/api/code/VirtualObject"))                       \
   GRAAL_ONLY(template(com_oracle_graal_api_code_RegisterSaveLayout,             "com/oracle/graal/api/code/RegisterSaveLayout"))                  \
   GRAAL_ONLY(template(com_oracle_graal_api_code_InvalidInstalledCodeException,  "com/oracle/graal/api/code/InvalidInstalledCodeException"))       \
--- a/src/share/vm/code/debugInfo.cpp	Fri Feb 27 16:35:54 2015 +0100
+++ b/src/share/vm/code/debugInfo.cpp	Fri Feb 27 16:36:38 2015 +0100
@@ -52,7 +52,7 @@
 #ifdef ASSERT
   assert(_obj_pool != NULL, "object pool does not exist");
   for (int i = _obj_pool->length() - 1; i >= 0; i--) {
-    assert(((ObjectValue*) _obj_pool->at(i))->id() != id, "should not be read twice");
+    assert(_obj_pool->at(i)->as_ObjectValue()->id() != id, "should not be read twice");
   }
 #endif
   ObjectValue* result = new ObjectValue(id);
@@ -66,7 +66,7 @@
   int id = read_int();
   assert(_obj_pool != NULL, "object pool does not exist");
   for (int i = _obj_pool->length() - 1; i >= 0; i--) {
-    ObjectValue* ov = (ObjectValue*) _obj_pool->at(i);
+    ObjectValue* ov = _obj_pool->at(i)->as_ObjectValue();
     if (ov->id() == id) {
       return ov;
     }
--- a/src/share/vm/code/debugInfo.hpp	Fri Feb 27 16:35:54 2015 +0100
+++ b/src/share/vm/code/debugInfo.hpp	Fri Feb 27 16:36:38 2015 +0100
@@ -41,6 +41,7 @@
 // - ConstantValue   describes a constant
 
 class ConstantOopReadValue;
+class ObjectValue;
 
 class ScopeValue: public ResourceObj {
  public:
@@ -58,6 +59,11 @@
     return (ConstantOopReadValue*) this;
   }
 
+  ObjectValue* as_ObjectValue() {
+    assert(is_object(), "must be");
+    return (ObjectValue*)this;
+  }
+
   // Serialization of debugging information
   virtual void write_on(DebugInfoWriteStream* stream) = 0;
   static ScopeValue* read_from(DebugInfoReadStream* stream);
--- a/src/share/vm/code/debugInfoRec.cpp	Fri Feb 27 16:35:54 2015 +0100
+++ b/src/share/vm/code/debugInfoRec.cpp	Fri Feb 27 16:36:38 2015 +0100
@@ -392,7 +392,7 @@
   PcDesc* last_pd = &_pcs[_pcs_length-1];
   if (objects != NULL) {
     for (int i = objects->length() - 1; i >= 0; i--) {
-      ((ObjectValue*) objects->at(i))->set_visited(false);
+      objects->at(i)->as_ObjectValue()->set_visited(false);
     }
   }
   int offset = serialize_scope_values(objects);
--- a/src/share/vm/code/nmethod.cpp	Fri Feb 27 16:35:54 2015 +0100
+++ b/src/share/vm/code/nmethod.cpp	Fri Feb 27 16:36:38 2015 +0100
@@ -2749,7 +2749,10 @@
       continue;
 
     ScopeDesc* sd = scope_desc_at(p->real_pc(this));
-    sd->print_on(tty, p);
+    while (sd != NULL) {
+      sd->print_on(tty, p);
+      sd = sd->sender();
+    }
   }
 }
 
--- a/src/share/vm/code/scopeDesc.cpp	Fri Feb 27 16:35:54 2015 +0100
+++ b/src/share/vm/code/scopeDesc.cpp	Fri Feb 27 16:36:38 2015 +0100
@@ -230,7 +230,7 @@
   if (NOT_GRAAL(DoEscapeAnalysis &&) is_top() && _objects != NULL) {
     tty->print_cr("Objects");
     for (int i = 0; i < _objects->length(); i++) {
-      ObjectValue* sv = (ObjectValue*) _objects->at(i);
+      ObjectValue* sv = _objects->at(i)->as_ObjectValue();
       tty->print(" - %d: ", sv->id());
       sv->print_fields_on(tty);
       tty->cr();
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Fri Feb 27 16:35:54 2015 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Fri Feb 27 16:36:38 2015 +0100
@@ -365,19 +365,19 @@
 }
 
 MonitorValue* CodeInstaller::get_monitor_value(oop value, int total_frame_size, GrowableArray<ScopeValue*>* objects, OopRecorder* oop_recorder) {
-  guarantee(value->is_a(HotSpotMonitorValue::klass()), "Monitors must be of type MonitorValue");
+  guarantee(value->is_a(StackLockValue::klass()), "Monitors must be of type MonitorValue");
 
   ScopeValue* second = NULL;
-  ScopeValue* owner_value = get_scope_value(HotSpotMonitorValue::owner(value), total_frame_size, objects, second, oop_recorder);
+  ScopeValue* owner_value = get_scope_value(StackLockValue::owner(value), total_frame_size, objects, second, oop_recorder);
   assert(second == NULL, "monitor cannot occupy two stack slots");
 
-  ScopeValue* lock_data_value = get_scope_value(HotSpotMonitorValue::slot(value), total_frame_size, objects, second, oop_recorder);
+  ScopeValue* lock_data_value = get_scope_value(StackLockValue::slot(value), total_frame_size, objects, second, oop_recorder);
   assert(second == lock_data_value, "monitor is LONG value that occupies two stack slots");
   assert(lock_data_value->is_location(), "invalid monitor location");
   Location lock_data_loc = ((LocationValue*)lock_data_value)->location();
 
   bool eliminated = false;
-  if (HotSpotMonitorValue::eliminated(value)) {
+  if (StackLockValue::eliminated(value)) {
     eliminated = true;
   }
 
--- a/src/share/vm/graal/graalJavaAccess.hpp	Fri Feb 27 16:35:54 2015 +0100
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Fri Feb 27 16:36:38 2015 +0100
@@ -243,10 +243,10 @@
     oop_field(VirtualObject, type, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                                             \
     objArrayOop_field(VirtualObject, values, "[Lcom/oracle/graal/api/meta/JavaValue;")                                                                         \
   end_class                                                                                                                                                    \
-  start_class(HotSpotMonitorValue)                                                                                                                             \
-    oop_field(HotSpotMonitorValue, owner, "Lcom/oracle/graal/api/meta/JavaValue;")                                                                             \
-    oop_field(HotSpotMonitorValue, slot, "Lcom/oracle/graal/api/code/StackSlotValue;")                                                                              \
-    boolean_field(HotSpotMonitorValue, eliminated)                                                                                                             \
+  start_class(StackLockValue)                                                                                                                                 \
+    oop_field(StackLockValue, owner, "Lcom/oracle/graal/api/meta/JavaValue;")                                                                                  \
+    oop_field(StackLockValue, slot, "Lcom/oracle/graal/api/code/StackSlotValue;")                                                                              \
+    boolean_field(StackLockValue, eliminated)                                                                                                                  \
   end_class                                                                                                                                                    \
   start_class(SpeculationLog)                                                                                                                                  \
     oop_field(SpeculationLog, lastFailed, "Ljava/lang/Object;")                                                                                                \
--- a/src/share/vm/runtime/vframe.cpp	Fri Feb 27 16:35:54 2015 +0100
+++ b/src/share/vm/runtime/vframe.cpp	Fri Feb 27 16:36:38 2015 +0100
@@ -274,7 +274,7 @@
   // Get oopmap describing oops and int for current bci
   InterpreterOopMap oop_mask;
   if ((TraceDeoptimization && Verbose) GRAAL_ONLY( || PrintDeoptimizationDetails)) {
-    methodHandle m_h(thread(), method());
+    methodHandle m_h(Thread::current(), method());
     OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
   } else {
     method()->mask_for(bci(), &oop_mask);