changeset 9339:bdf4604fec2e

Merge.
author Doug Simon <doug.simon@oracle.com>
date Fri, 26 Apr 2013 18:38:56 +0200
parents 0266549ff6e0 (current diff) d9b3221c577d (diff)
children cbc0b38db597
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/AllocatableValue.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java src/share/vm/graal/graalJavaAccess.hpp
diffstat 85 files changed, 633 insertions(+), 611 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/AllocatableValue.java	Fri Apr 26 18:36:41 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * 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.api.code;
-
-import com.oracle.graal.api.meta.*;
-
-/**
- * Common base class for values that can be manipulated by the register allocator.
- */
-public abstract class AllocatableValue extends Value {
-
-    private static final long serialVersionUID = 153019506717492133L;
-
-    /**
-     * Marker to tell the register allocator that no storage location needs to be allocated for this
-     * value.
-     */
-    @SuppressWarnings("serial") public static final AllocatableValue UNUSED = new AllocatableValue(Kind.Illegal) {
-
-        @Override
-        public String toString() {
-            return "-";
-        }
-    };
-
-    public AllocatableValue(Kind kind) {
-        super(kind);
-    }
-
-}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java	Fri Apr 26 18:38:56 2013 +0200
@@ -76,17 +76,17 @@
      */
     private final int stackSize;
 
-    private final Value returnLocation;
+    private final AllocatableValue returnLocation;
 
     /**
      * The ordered locations in which the arguments are placed.
      */
-    private final Value[] argumentLocations;
+    private final AllocatableValue[] argumentLocations;
 
     /**
      * The locations used (and killed) by the call in addition to the arguments.
      */
-    private final Value[] temporaryLocations;
+    private final AllocatableValue[] temporaryLocations;
 
     /**
      * Creates a description of the registers and stack locations used by a call.
@@ -97,8 +97,8 @@
      *            call
      * @param argumentLocations the ordered locations in which the arguments are placed
      */
-    public CallingConvention(int stackSize, Value returnLocation, Value... argumentLocations) {
-        this(Value.NONE, stackSize, returnLocation, argumentLocations);
+    public CallingConvention(int stackSize, AllocatableValue returnLocation, AllocatableValue... argumentLocations) {
+        this(AllocatableValue.NONE, stackSize, returnLocation, argumentLocations);
     }
 
     /**
@@ -112,7 +112,7 @@
      *            call
      * @param argumentLocations the ordered locations in which the arguments are placed
      */
-    public CallingConvention(Value[] temporaryLocations, int stackSize, Value returnLocation, Value... argumentLocations) {
+    public CallingConvention(AllocatableValue[] temporaryLocations, int stackSize, AllocatableValue returnLocation, AllocatableValue... argumentLocations) {
         assert argumentLocations != null;
         assert temporaryLocations != null;
         assert returnLocation != null;
@@ -126,14 +126,14 @@
     /**
      * Gets the location for the return value or {@link Value#ILLEGAL} if a void call.
      */
-    public Value getReturn() {
+    public AllocatableValue getReturn() {
         return returnLocation;
     }
 
     /**
      * Gets the location for the {@code index}'th argument.
      */
-    public Value getArgument(int index) {
+    public AllocatableValue getArgument(int index) {
         return argumentLocations[index];
     }
 
@@ -155,7 +155,7 @@
      * Gets the locations used (and killed) by the call apart from the
      * {@linkplain #getArgument(int) arguments}.
      */
-    public Value[] getTemporaries() {
+    public AllocatableValue[] getTemporaries() {
         if (temporaryLocations.length == 0) {
             return temporaryLocations;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/AllocatableValue.java	Fri Apr 26 18:38:56 2013 +0200
@@ -0,0 +1,39 @@
+/*
+ * 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.api.meta;
+
+/**
+ * Common base class for values that are stored in some location that's managed by the register
+ * allocator (e.g. register, stack slot).
+ */
+public abstract class AllocatableValue extends Value {
+
+    private static final long serialVersionUID = 153019506717492133L;
+
+    public static final AllocatableValue[] NONE = {};
+
+    public AllocatableValue(Kind kind) {
+        super(kind);
+    }
+
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Value.java	Fri Apr 26 18:38:56 2013 +0200
@@ -32,9 +32,7 @@
 
     private static final long serialVersionUID = -6909397188697766469L;
 
-    public static final Value[] NONE = {};
-
-    @SuppressWarnings("serial") public static final Value ILLEGAL = new Value(Kind.Illegal) {
+    @SuppressWarnings("serial") public static final AllocatableValue ILLEGAL = new AllocatableValue(Kind.Illegal) {
 
         @Override
         public String toString() {
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Fri Apr 26 18:38:56 2013 +0200
@@ -90,7 +90,7 @@
     public static class AMD64SpillMoveFactory implements LIR.SpillMoveFactory {
 
         @Override
-        public LIRInstruction createMove(Value result, Value input) {
+        public LIRInstruction createMove(AllocatableValue result, Value input) {
             return AMD64LIRGenerator.createMove(result, input);
         }
     }
@@ -143,8 +143,10 @@
         return result;
     }
 
-    private static AMD64LIRInstruction createMove(Value dst, Value src) {
-        if (isRegister(src) || isStackSlot(dst)) {
+    private static AMD64LIRInstruction createMove(AllocatableValue dst, Value src) {
+        if (src instanceof AMD64AddressValue) {
+            return new LeaOp(dst, (AMD64AddressValue) src);
+        } else if (isRegister(src) || isStackSlot(dst)) {
             return new MoveFromRegOp(dst, src);
         } else {
             return new MoveToRegOp(dst, src);
@@ -152,24 +154,23 @@
     }
 
     @Override
-    public void emitMove(Value dst, Value src) {
+    public void emitMove(AllocatableValue dst, Value src) {
         append(createMove(dst, src));
     }
 
-    private AMD64AddressValue prepareAddress(Kind kind, Value base, long displacement, Value index, int scale) {
+    @Override
+    public AMD64AddressValue emitAddress(Value base, long displacement, Value index, int scale) {
         AllocatableValue baseRegister;
         long finalDisp = displacement;
         if (isConstant(base)) {
             if (asConstant(base).isNull()) {
-                baseRegister = AllocatableValue.UNUSED;
+                baseRegister = Value.ILLEGAL;
             } else if (asConstant(base).getKind() != Kind.Object && !runtime.needsDataPatch(asConstant(base))) {
                 finalDisp += asConstant(base).asLong();
-                baseRegister = AllocatableValue.UNUSED;
+                baseRegister = Value.ILLEGAL;
             } else {
                 baseRegister = load(base);
             }
-        } else if (base == Value.ILLEGAL) {
-            baseRegister = AllocatableValue.UNUSED;
         } else {
             baseRegister = asAllocatable(base);
         }
@@ -180,12 +181,12 @@
             scaleEnum = Scale.fromInt(scale);
             if (isConstant(index)) {
                 finalDisp += asConstant(index).asLong() * scale;
-                indexRegister = AllocatableValue.UNUSED;
+                indexRegister = Value.ILLEGAL;
             } else {
                 indexRegister = asAllocatable(index);
             }
         } else {
-            indexRegister = AllocatableValue.UNUSED;
+            indexRegister = Value.ILLEGAL;
             scaleEnum = Scale.Times1;
         }
 
@@ -195,9 +196,9 @@
         } else {
             displacementInt = 0;
             AllocatableValue displacementRegister = load(Constant.forLong(finalDisp));
-            if (baseRegister == AllocatableValue.UNUSED) {
+            if (baseRegister == Value.ILLEGAL) {
                 baseRegister = displacementRegister;
-            } else if (indexRegister == AllocatableValue.UNUSED) {
+            } else if (indexRegister == Value.ILLEGAL) {
                 indexRegister = displacementRegister;
                 scaleEnum = Scale.Times1;
             } else {
@@ -205,44 +206,44 @@
             }
         }
 
-        return new AMD64AddressValue(kind, baseRegister, indexRegister, scaleEnum, displacementInt);
+        return new AMD64AddressValue(target().wordKind, baseRegister, indexRegister, scaleEnum, displacementInt);
+    }
+
+    private AMD64AddressValue asAddress(Value address) {
+        if (address instanceof AMD64AddressValue) {
+            return (AMD64AddressValue) address;
+        } else {
+            return emitAddress(address, 0, Value.ILLEGAL, 0);
+        }
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode deopting) {
-        AMD64AddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale);
-        Variable result = newVariable(loadAddress.getKind());
-        append(new LoadOp(result, loadAddress, deopting != null ? state(deopting) : null));
+    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode deopting) {
+        AMD64AddressValue loadAddress = asAddress(address);
+        Variable result = newVariable(kind);
+        append(new LoadOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) {
-        AMD64AddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale);
+    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) {
+        AMD64AddressValue storeAddress = asAddress(address);
         LIRFrameState state = deopting != null ? state(deopting) : null;
 
         if (isConstant(inputVal)) {
             Constant c = asConstant(inputVal);
             if (canStoreConstant(c)) {
-                append(new StoreConstantOp(storeAddress, c, state));
+                append(new StoreConstantOp(kind, storeAddress, c, state));
                 return;
             }
         }
 
         Variable input = load(inputVal);
-        append(new StoreOp(storeAddress, input, state));
+        append(new StoreOp(kind, storeAddress, input, state));
     }
 
     @Override
-    public Variable emitLea(Value base, long displacement, Value index, int scale) {
-        Variable result = newVariable(target().wordKind);
-        AMD64AddressValue address = prepareAddress(result.getKind(), base, displacement, index, scale);
-        append(new LeaOp(result, address));
-        return result;
-    }
-
-    @Override
-    public Variable emitLea(StackSlot address) {
+    public Variable emitAddress(StackSlot address) {
         Variable result = newVariable(target().wordKind);
         append(new StackLeaOp(result, address));
         return result;
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Fri Apr 26 18:38:56 2013 +0200
@@ -28,17 +28,13 @@
 import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*;
 import static com.oracle.graal.lir.ptx.PTXCompare.*;
 
-import com.oracle.graal.api.code.AllocatableValue;
 import com.oracle.graal.api.code.CodeCacheProvider;
 import com.oracle.graal.api.code.DeoptimizationAction;
 import com.oracle.graal.api.code.RuntimeCallTarget;
 import com.oracle.graal.api.code.StackSlot;
 import com.oracle.graal.api.code.TargetDescription;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
-import com.oracle.graal.api.meta.Constant;
-import com.oracle.graal.api.meta.Kind;
-import com.oracle.graal.api.meta.ResolvedJavaMethod;
-import com.oracle.graal.api.meta.Value;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.NumUtil;
 import com.oracle.graal.compiler.gen.LIRGenerator;
 import com.oracle.graal.compiler.target.LIRGenLowerable;
@@ -84,7 +80,7 @@
     public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory {
 
         @Override
-        public LIRInstruction createMove(Value result, Value input) {
+        public LIRInstruction createMove(AllocatableValue result, Value input) {
             throw new InternalError("NYI");
         }
     }
@@ -129,7 +125,7 @@
     }
 
     @Override
-    public void emitMove(Value dst, Value src) {
+    public void emitMove(AllocatableValue dst, Value src) {
         if (isRegister(src) || isStackSlot(dst)) {
             append(new MoveFromRegOp(dst, src));
         } else {
@@ -137,20 +133,19 @@
         }
     }
 
-    private PTXAddressValue prepareAddress(Kind kind, Value base, long displacement, Value index, int scale) {
+    @Override
+    public PTXAddressValue emitAddress(Value base, long displacement, Value index, int scale) {
         AllocatableValue baseRegister;
         long finalDisp = displacement;
         if (isConstant(base)) {
             if (asConstant(base).isNull()) {
-                baseRegister = AllocatableValue.UNUSED;
+                baseRegister = Value.ILLEGAL;
             } else if (asConstant(base).getKind() != Kind.Object) {
                 finalDisp += asConstant(base).asLong();
-                baseRegister = AllocatableValue.UNUSED;
+                baseRegister = Value.ILLEGAL;
             } else {
                 baseRegister = load(base);
             }
-        } else if (base == Value.ILLEGAL) {
-            baseRegister = AllocatableValue.UNUSED;
         } else {
             baseRegister = asAllocatable(base);
         }
@@ -166,7 +161,7 @@
                     indexRegister = index;
                 }
 
-                if (baseRegister == AllocatableValue.UNUSED) {
+                if (baseRegister == Value.ILLEGAL) {
                     baseRegister = asAllocatable(indexRegister);
                 } else {
                     Variable newBase = newVariable(Kind.Int);
@@ -177,31 +172,34 @@
             }
         }
 
-        return new PTXAddressValue(kind, baseRegister, finalDisp);
+        return new PTXAddressValue(target().wordKind, baseRegister, finalDisp);
+    }
+
+    private PTXAddressValue asAddress(Value address) {
+        if (address instanceof PTXAddressValue) {
+            return (PTXAddressValue) address;
+        } else {
+            return emitAddress(address, 0, Value.ILLEGAL, 0);
+        }
     }
 
     @Override
-    public Variable emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode deopting) {
-        PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale);
-        Variable result = newVariable(loadAddress.getKind());
-        append(new LoadOp(result, loadAddress, deopting != null ? state(deopting) : null));
+    public Variable emitLoad(Kind kind, Value address, DeoptimizingNode deopting) {
+        PTXAddressValue loadAddress = asAddress(address);
+        Variable result = newVariable(kind);
+        append(new LoadOp(kind, result, loadAddress, deopting != null ? state(deopting) : null));
         return result;
     }
 
     @Override
-    public void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) {
-        PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale);
+    public void emitStore(Kind kind, Value address, Value inputVal, DeoptimizingNode deopting) {
+        PTXAddressValue storeAddress = asAddress(address);
         Variable input = load(inputVal);
-        append(new StoreOp(storeAddress, input, deopting != null ? state(deopting) : null));
+        append(new StoreOp(kind, storeAddress, input, deopting != null ? state(deopting) : null));
     }
 
     @Override
-    public Variable emitLea(Value base, long displacement, Value index, int scale) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
-    public Variable emitLea(StackSlot address) {
+    public Variable emitAddress(StackSlot address) {
         throw new InternalError("NYI");
     }
 
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Fri Apr 26 18:38:56 2013 +0200
@@ -208,31 +208,31 @@
     }
 
     @Override
-    public void emitMove(Value dst, Value src) {
+    public void emitMove(AllocatableValue dst, Value src) {
         // SPARC: Auto-generated method stub
 
     }
 
     @Override
-    public Value emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode canTrap) {
+    public Value emitAddress(Value base, long displacement, Value index, int scale) {
         // SPARC: Auto-generated method stub
         return null;
     }
 
     @Override
-    public void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value input, DeoptimizingNode canTrap) {
+    public Value emitLoad(Kind kind, Value address, DeoptimizingNode canTrap) {
+        // SPARC: Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void emitStore(Kind kind, Value address, Value input, DeoptimizingNode canTrap) {
         // SPARC: Auto-generated method stub
 
     }
 
     @Override
-    public Value emitLea(Value base, long displacement, Value index, int scale) {
-        // SPARC: Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Value emitLea(StackSlot address) {
+    public Value emitAddress(StackSlot address) {
         // SPARC: Auto-generated method stub
         return null;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Fri Apr 26 18:38:56 2013 +0200
@@ -22,15 +22,11 @@
  */
 package com.oracle.graal.compiler.test;
 
-import java.util.*;
-
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.Lowerable.*;
 import com.oracle.graal.phases.common.*;
@@ -96,36 +92,10 @@
 
                 Debug.dump(graph, "After lowering");
 
-                ArrayList<MergeNode> merges = new ArrayList<>();
-                ArrayList<FloatingReadNode> reads = new ArrayList<>();
-                for (Node n : graph.getNodes()) {
-                    if (n instanceof MergeNode) {
-                        // check shape
-                        MergeNode merge = (MergeNode) n;
-
-                        if (merge.inputs().count() == 2) {
-                            for (EndNode m : merge.forwardEnds()) {
-                                if (m.predecessor() != null && m.predecessor() instanceof BeginNode && m.predecessor().predecessor() instanceof IfNode) {
-                                    IfNode o = (IfNode) m.predecessor().predecessor();
-                                    if (o.falseSuccessor().next() instanceof DeoptimizeNode) {
-                                        merges.add(merge);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    if (n instanceof IntegerAddNode) {
-                        IntegerAddNode ian = (IntegerAddNode) n;
-
-                        Assert.assertTrue(ian.y() instanceof ConstantNode);
-                        Assert.assertTrue(ian.x() instanceof FloatingReadNode);
-                        reads.add((FloatingReadNode) ian.x());
-                    }
-                }
-
-                Assert.assertTrue(merges.size() >= reads.size());
-                for (int i = 0; i < reads.size(); i++) {
-                    assertOrderedAfterSchedule(graph, merges.get(i), reads.get(i));
+                for (FloatingReadNode node : graph.getNodes(LocalNode.class).first().usages().filter(FloatingReadNode.class)) {
+                    // Checking that the parameter a is not directly used for the access to field
+                    // x10 (because x10 must be guarded by the checkcast).
+                    Assert.assertTrue(node.location().locationIdentity() == LocationNode.FINAL_LOCATION);
                 }
             }
         });
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Fri Apr 26 18:38:56 2013 +0200
@@ -409,7 +409,7 @@
      * The {@linkplain RegisterValue register} or {@linkplain Variable variable} for this interval
      * prior to register allocation.
      */
-    public final Value operand;
+    public final AllocatableValue operand;
 
     /**
      * The operand number for this interval's {@linkplain #operand operand}.
@@ -420,7 +420,7 @@
      * The {@linkplain RegisterValue register} or {@linkplain StackSlot spill slot} assigned to this
      * interval.
      */
-    private Value location;
+    private AllocatableValue location;
 
     /**
      * The stack slot to which all splits of this interval are spilled if necessary.
@@ -498,7 +498,7 @@
      */
     private Interval locationHint;
 
-    void assignLocation(Value newLocation) {
+    void assignLocation(AllocatableValue newLocation) {
         if (isRegister(newLocation)) {
             assert this.location == null : "cannot re-assign location for " + this;
             if (newLocation.getKind() == Kind.Illegal && kind != Kind.Illegal) {
@@ -518,7 +518,7 @@
      * Gets the {@linkplain RegisterValue register} or {@linkplain StackSlot spill slot} assigned to
      * this interval.
      */
-    public Value location() {
+    public AllocatableValue location() {
         return location;
     }
 
@@ -673,7 +673,7 @@
      */
     static final Interval EndMarker = new Interval(Value.ILLEGAL, -1);
 
-    Interval(Value operand, int operandNumber) {
+    Interval(AllocatableValue operand, int operandNumber) {
         assert operand != null;
         this.operand = operand;
         this.operandNumber = operandNumber;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Fri Apr 26 18:38:56 2013 +0200
@@ -206,7 +206,7 @@
     /**
      * Gets the operand denoted by a given operand number.
      */
-    private Value operandFor(int operandNumber) {
+    private AllocatableValue operandFor(int operandNumber) {
         if (operandNumber < firstVariableNumber) {
             assert operandNumber >= 0;
             return registers[operandNumber].asValue();
@@ -281,7 +281,7 @@
      * @param operand the operand for the interval
      * @return the created interval
      */
-    Interval createInterval(Value operand) {
+    Interval createInterval(AllocatableValue operand) {
         assert isLegal(operand);
         int operandNumber = operandNumber(operand);
         Interval interval = new Interval(operand, operandNumber);
@@ -346,7 +346,7 @@
         return intervals[operandNumber];
     }
 
-    Interval getOrCreateInterval(Value operand) {
+    Interval getOrCreateInterval(AllocatableValue operand) {
         Interval ret = intervalFor(operand);
         if (ret == null) {
             return createInterval(operand);
@@ -555,8 +555,8 @@
                             insertionBuffer.init(instructions);
                         }
 
-                        Value fromLocation = interval.location();
-                        Value toLocation = canonicalSpillOpr(interval);
+                        AllocatableValue fromLocation = interval.location();
+                        AllocatableValue toLocation = canonicalSpillOpr(interval);
 
                         assert isRegister(fromLocation) : "from operand must be a register but is: " + fromLocation + " toLocation=" + toLocation + " spillState=" + interval.spillState();
                         assert isStackSlot(toLocation) : "to operand must be a stack slot";
@@ -968,7 +968,7 @@
         TTY.println(blockData.get(block).liveOut.toString());
     }
 
-    void addUse(Value operand, int from, int to, RegisterPriority registerPriority, Kind kind) {
+    void addUse(AllocatableValue operand, int from, int to, RegisterPriority registerPriority, Kind kind) {
         if (!isProcessed(operand)) {
             return;
         }
@@ -987,7 +987,7 @@
         interval.addUsePos(to & ~1, registerPriority);
     }
 
-    void addTemp(Value operand, int tempPos, RegisterPriority registerPriority, Kind kind) {
+    void addTemp(AllocatableValue operand, int tempPos, RegisterPriority registerPriority, Kind kind) {
         if (!isProcessed(operand)) {
             return;
         }
@@ -1008,7 +1008,7 @@
         return !isRegister(operand) || attributes(asRegister(operand)).isAllocatable();
     }
 
-    void addDef(Value operand, int defPos, RegisterPriority registerPriority, Kind kind) {
+    void addDef(AllocatableValue operand, int defPos, RegisterPriority registerPriority, Kind kind) {
         if (!isProcessed(operand)) {
             return;
         }
@@ -1114,8 +1114,8 @@
                 @Override
                 protected Value doValue(Value registerHint) {
                     if (isVariableOrRegister(registerHint)) {
-                        Interval from = getOrCreateInterval(registerHint);
-                        Interval to = getOrCreateInterval(targetValue);
+                        Interval from = getOrCreateInterval((AllocatableValue) registerHint);
+                        Interval to = getOrCreateInterval((AllocatableValue) targetValue);
 
                         // hints always point from def to use
                         if (hintAtDef) {
@@ -1156,7 +1156,7 @@
             BitSet live = blockData.get(block).liveOut;
             for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) {
                 assert live.get(operandNum) : "should not stop here otherwise";
-                Value operand = operandFor(operandNum);
+                AllocatableValue operand = operandFor(operandNum);
                 if (GraalOptions.TraceLinearScanLevel >= 2) {
                     TTY.println("live in %s to %d", operand, blockTo + 2);
                 }
@@ -1197,7 +1197,7 @@
                     @Override
                     public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                         if (isVariableOrRegister(operand)) {
-                            addDef(operand, opId, registerPriorityOfOutputOperand(op), operand.getKind().getStackKind());
+                            addDef((AllocatableValue) operand, opId, registerPriorityOfOutputOperand(op), operand.getKind().getStackKind());
                             addRegisterHint(op, operand, mode, flags, true);
                         }
                         return operand;
@@ -1208,7 +1208,7 @@
                     @Override
                     public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                         if (isVariableOrRegister(operand)) {
-                            addTemp(operand, opId, RegisterPriority.MustHaveRegister, operand.getKind().getStackKind());
+                            addTemp((AllocatableValue) operand, opId, RegisterPriority.MustHaveRegister, operand.getKind().getStackKind());
                             addRegisterHint(op, operand, mode, flags, false);
                         }
                         return operand;
@@ -1220,7 +1220,7 @@
                     public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                         if (isVariableOrRegister(operand)) {
                             RegisterPriority p = registerPriorityOfInputOperand(flags);
-                            addUse(operand, blockFrom, opId + 1, p, operand.getKind().getStackKind());
+                            addUse((AllocatableValue) operand, blockFrom, opId + 1, p, operand.getKind().getStackKind());
                             addRegisterHint(op, operand, mode, flags, false);
                         }
                         return operand;
@@ -1232,7 +1232,7 @@
                     public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
                         if (isVariableOrRegister(operand)) {
                             RegisterPriority p = registerPriorityOfInputOperand(flags);
-                            addUse(operand, blockFrom, opId, p, operand.getKind().getStackKind());
+                            addUse((AllocatableValue) operand, blockFrom, opId, p, operand.getKind().getStackKind());
                             addRegisterHint(op, operand, mode, flags, false);
                         }
                         return operand;
@@ -1247,7 +1247,7 @@
 
                     @Override
                     public Value doValue(Value operand) {
-                        addUse(operand, blockFrom, opId + 1, RegisterPriority.None, operand.getKind().getStackKind());
+                        addUse((AllocatableValue) operand, blockFrom, opId + 1, RegisterPriority.None, operand.getKind().getStackKind());
                         return operand;
                     }
                 });
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java	Fri Apr 26 18:38:56 2013 +0200
@@ -196,8 +196,8 @@
         assert fromInterval.kind() == toInterval.kind() : "move between different types";
         assert insertIdx != -1 : "must setup insert position first";
 
-        Value fromOpr = fromInterval.operand;
-        Value toOpr = toInterval.operand;
+        AllocatableValue fromOpr = fromInterval.operand;
+        AllocatableValue toOpr = toInterval.operand;
 
         insertionBuffer.append(insertIdx, allocator.ir.spillMoveFactory.createMove(toOpr, fromOpr));
 
@@ -210,7 +210,7 @@
         assert fromOpr.getKind() == toInterval.kind() : "move between different types";
         assert insertIdx != -1 : "must setup insert position first";
 
-        Value toOpr = toInterval.operand;
+        AllocatableValue toOpr = toInterval.operand;
         insertionBuffer.append(insertIdx, allocator.ir.spillMoveFactory.createMove(toOpr, fromOpr));
 
         if (GraalOptions.TraceLinearScanLevel >= 4) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Apr 26 18:38:56 2013 +0200
@@ -52,7 +52,7 @@
 /**
  * This class traverses the HIR instructions and generates LIR instructions from them.
  */
-public abstract class LIRGenerator extends LIRGeneratorTool {
+public abstract class LIRGenerator implements LIRGeneratorTool {
 
     public final FrameMap frameMap;
     public final NodeMap<Value> nodeOperands;
@@ -168,8 +168,8 @@
 
     @Override
     public Value setResult(ValueNode x, Value operand) {
-        assert (isVariable(operand) && x.kind() == operand.getKind()) || (isRegister(operand) && !attributes(asRegister(operand)).isAllocatable()) ||
-                        (isConstant(operand) && x.kind() == operand.getKind().getStackKind()) : operand.getKind() + " for node " + x;
+        assert (!isVariable(operand) || x.kind() == operand.getKind()) : operand.getKind() + " for node " + x;
+        assert (!isRegister(operand) || !attributes(asRegister(operand)).isAllocatable());
         assert operand(x) == null : "operand cannot be set twice";
         assert operand != null && isLegal(operand) : "operand must be legal";
         assert operand.getKind().getStackKind() == x.kind() : operand.getKind().getStackKind() + " must match " + x.kind();
@@ -251,7 +251,7 @@
      * @return the operand representing the ABI defined location used return a value of kind
      *         {@code kind}
      */
-    public Value resultOperandFor(Kind kind) {
+    public AllocatableValue resultOperandFor(Kind kind) {
         if (kind == Kind.Void) {
             return ILLEGAL;
         }
@@ -461,7 +461,7 @@
 
     @Override
     public void visitReturn(ReturnNode x) {
-        Value operand = Value.ILLEGAL;
+        AllocatableValue operand = ILLEGAL;
         if (x.result() != null) {
             operand = resultOperandFor(x.result().kind());
             emitMove(operand, operand(x.result()));
@@ -630,7 +630,7 @@
 
     protected abstract void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info);
 
-    protected static Value toStackKind(Value value) {
+    protected static AllocatableValue toStackKind(AllocatableValue value) {
         if (value.getKind().getStackKind() != value.getKind()) {
             // We only have stack-kinds in the LIR, so convert the operand kind for values from the
             // calling convention.
@@ -651,7 +651,7 @@
         int j = 0;
         for (ValueNode arg : arguments) {
             if (arg != null) {
-                Value operand = toStackKind(cc.getArgument(j));
+                AllocatableValue operand = toStackKind(cc.getArgument(j));
                 emitMove(operand, operand(arg));
                 result[j] = operand;
                 j++;
@@ -672,7 +672,7 @@
         Value[] argLocations = new Value[args.length];
         for (int i = 0; i < args.length; i++) {
             Value arg = args[i];
-            Value loc = cc.getArgument(i);
+            AllocatableValue loc = cc.getArgument(i);
             emitMove(loc, arg);
             argLocations[i] = loc;
         }
@@ -826,6 +826,10 @@
         return frameMap;
     }
 
+    @Override
+    public void beforeRegisterAllocation() {
+    }
+
     public abstract void emitBitCount(Variable result, Value operand);
 
     public abstract void emitBitScanForward(Variable result, Value operand);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java	Fri Apr 26 18:38:56 2013 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.compiler.gen;
 
+import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
-import static com.oracle.graal.api.code.ValueUtil.*;
 
 import java.util.*;
 
@@ -187,7 +187,7 @@
     private void emitMove(Value dest, Value src) {
         assert isLegal(src);
         assert isLegal(dest);
-        gen.emitMove(dest, src);
+        gen.emitMove((AllocatableValue) dest, src);
     }
 
     // Traverse assignment graph in depth first order and generate moves in post order
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraalInternalError.java	Fri Apr 26 18:38:56 2013 +0200
@@ -51,6 +51,23 @@
     }
 
     /**
+     * Checks a given condition and throws a {@link GraalInternalError} if it is false. Guarantees
+     * are stronger than assertions in that they are always checked. Error messages for guarantee
+     * violations should clearly indicate the nature of the problem as well as a suggested solution
+     * if possible.
+     * 
+     * @param condition the condition to check
+     * @param msg the message that will be associated with the error, in
+     *            {@link String#format(String, Object...)} syntax
+     * @param args arguments to the format string
+     */
+    public static void guarantee(boolean condition, String msg, Object... args) {
+        if (!condition) {
+            throw new GraalInternalError("failed guarantee: " + msg, args);
+        }
+    }
+
+    /**
      * This constructor creates a {@link GraalInternalError} with a message assembled via
      * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to
      * always generate the same output.
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Apr 26 18:38:56 2013 +0200
@@ -27,6 +27,7 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.hotspot.amd64.AMD64HotSpotUnwindOp.*;
 
+import java.lang.reflect.*;
 import java.util.*;
 
 import com.oracle.graal.amd64.*;
@@ -301,6 +302,7 @@
         } else {
             assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special;
             HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target();
+            assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method.";
             Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant();
             append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod));
         }
@@ -308,9 +310,9 @@
 
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        Value metaspaceMethod = AMD64.rbx.asValue();
+        AllocatableValue metaspaceMethod = AMD64.rbx.asValue();
         emitMove(metaspaceMethod, operand(((HotSpotIndirectCallTargetNode) callTarget).metaspaceMethod()));
-        Value targetAddress = AMD64.rax.asValue();
+        AllocatableValue targetAddress = AMD64.rax.asValue();
         emitMove(targetAddress, operand(callTarget.computedAddress()));
         append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState));
     }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Fri Apr 26 18:38:56 2013 +0200
@@ -143,7 +143,7 @@
     }
 
     private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) {
-        Value[] locations = new Value[parameterTypes.length];
+        AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
 
         int currentGeneral = 0;
         int currentXMM = 0;
@@ -183,7 +183,7 @@
         }
 
         Kind returnKind = returnType == null ? Kind.Void : returnType.getKind();
-        Value returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind);
+        AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind);
         return new CallingConvention(currentStackOffset, returnLocation, locations);
     }
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java	Fri Apr 26 18:38:56 2013 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.amd64.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java	Fri Apr 26 18:38:56 2013 +0200
@@ -27,6 +27,7 @@
 import sun.misc.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java	Fri Apr 26 18:38:56 2013 +0200
@@ -91,13 +91,13 @@
             assert stub != null : "linkage without an address must be a stub";
             InstalledCode code = stub.getCode(backend);
 
-            Value[] argumentLocations = new Value[cc.getArgumentCount()];
+            AllocatableValue[] argumentLocations = new AllocatableValue[cc.getArgumentCount()];
             for (int i = 0; i < argumentLocations.length; i++) {
                 argumentLocations[i] = cc.getArgument(i);
             }
 
             Set<Register> definedRegisters = stub.getDefinedRegisters();
-            Value[] temporaryLocations = new Value[definedRegisters.size()];
+            AllocatableValue[] temporaryLocations = new AllocatableValue[definedRegisters.size()];
             int i = 0;
             for (Register reg : definedRegisters) {
                 temporaryLocations[i++] = reg.asValue();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Fri Apr 26 18:38:56 2013 +0200
@@ -48,8 +48,8 @@
 import com.oracle.graal.api.code.CodeUtil.RefMapFormatter;
 import com.oracle.graal.api.code.CompilationResult.Call;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
+import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.api.code.CompilationResult.Mark;
-import com.oracle.graal.api.code.CompilationResult.Infopoint;
 import com.oracle.graal.api.code.Register.RegisterFlag;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
@@ -164,23 +164,23 @@
         }
     }
 
-    protected Value ret(Kind kind) {
+    protected AllocatableValue ret(Kind kind) {
         if (kind == Kind.Void) {
             return ILLEGAL;
         }
         return globalStubRegConfig.getReturnRegister(kind).asValue(kind);
     }
 
-    protected Value[] javaCallingConvention(Kind... arguments) {
+    protected AllocatableValue[] javaCallingConvention(Kind... arguments) {
         return callingConvention(arguments, RuntimeCall);
     }
 
-    protected Value[] nativeCallingConvention(Kind... arguments) {
+    protected AllocatableValue[] nativeCallingConvention(Kind... arguments) {
         return callingConvention(arguments, NativeCall);
     }
 
-    private Value[] callingConvention(Kind[] arguments, CallingConvention.Type type) {
-        Value[] result = new Value[arguments.length];
+    private AllocatableValue[] callingConvention(Kind[] arguments, CallingConvention.Type type) {
+        AllocatableValue[] result = new AllocatableValue[arguments.length];
 
         TargetDescription target = graalRuntime.getTarget();
         int currentStackOffset = 0;
@@ -286,7 +286,7 @@
      * @param ret where the call returns its result
      * @param args where arguments are passed to the call
      */
-    protected RuntimeCallTarget addStubCall(Descriptor descriptor, Value ret, Value... args) {
+    protected RuntimeCallTarget addStubCall(Descriptor descriptor, AllocatableValue ret, AllocatableValue... args) {
         return addRuntimeCall(descriptor, 0L, null, ret, args);
     }
 
@@ -299,8 +299,8 @@
      * @param ret where the call returns its result
      * @param args where arguments are passed to the call
      */
-    protected RuntimeCallTarget addRuntimeCall(Descriptor descriptor, long address, Register[] tempRegs, Value ret, Value... args) {
-        Value[] temps = tempRegs == null || tempRegs.length == 0 ? Value.NONE : new Value[tempRegs.length];
+    protected RuntimeCallTarget addRuntimeCall(Descriptor descriptor, long address, Register[] tempRegs, AllocatableValue ret, AllocatableValue... args) {
+        AllocatableValue[] temps = tempRegs == null || tempRegs.length == 0 ? AllocatableValue.NONE : new AllocatableValue[tempRegs.length];
         for (int i = 0; i < temps.length; i++) {
             temps[i] = tempRegs[i].asValue();
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -73,7 +73,7 @@
         HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen;
         StackSlot slot = hsGen.getLockSlot(lockDepth);
         if (!eliminated) {
-            Value result = gen.emitLea(slot);
+            Value result = gen.emitAddress(slot);
             gen.setResult(this, result);
         }
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -57,7 +57,7 @@
         HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen;
         StackSlot slot = hsGen.getLockSlot(lockDepth);
         // The register allocator cannot handle stack -> register moves so we use an LEA here
-        Value result = gen.emitMove(gen.emitLea(slot));
+        Value result = gen.emitMove(gen.emitAddress(slot));
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -47,7 +47,7 @@
     public void generate(LIRGenerator gen) {
         int size = rank * 4;
         StackSlot array = gen.frameMap().allocateStackBlock(size, false);
-        Value result = gen.emitLea(array);
+        Value result = gen.emitAddress(array);
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/GetObjectAddressNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -46,7 +46,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        Value obj = gen.newVariable(gen.target().wordKind);
+        AllocatableValue obj = gen.newVariable(gen.target().wordKind);
         gen.emitMove(obj, gen.operand(object));
         gen.setResult(this, obj);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -43,7 +43,7 @@
     public void generate(LIRGenerator gen) {
         assert graph().getNodes().filter(MonitorCounterNode.class).count() == 1 : "monitor counters not canonicalized to single instance";
         StackSlot counter = gen.frameMap().allocateStackBlock(gen.target().wordSize, false);
-        Value result = gen.emitLea(counter);
+        Value result = gen.emitAddress(counter);
         gen.setResult(this, result);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java	Fri Apr 26 18:38:56 2013 +0200
@@ -60,7 +60,7 @@
         HotSpotLIRGenerator hsGen = (HotSpotLIRGenerator) gen;
         StackSlot slot = hsGen.getLockSlot(lockDepth);
         RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(MonitorExitStubCall.MONITOREXIT);
-        gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object), gen.emitLea(slot));
+        gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(object), gen.emitAddress(slot));
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -71,7 +71,8 @@
             parameters.add(frameState.localAt(slot));
         }
         Value[] args = gen.visitInvokeArguments(cc, parameters);
-        Value entry = gen.emitLoad(Kind.Long, gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0, null);
+        Value address = gen.emitAddress(gen.operand(target), config.nmethodEntryOffset, Value.ILLEGAL, 0);
+        Value entry = gen.emitLoad(Kind.Long, address, null);
         HotSpotLIRGenerator hsgen = (HotSpotLIRGenerator) gen;
         hsgen.emitTailcall(args, entry);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Apr 26 18:38:56 2013 +0200
@@ -84,8 +84,8 @@
         long nonVectorBytes = byteLength % VECTOR_SIZE;
         long srcOffset = (long) srcPos * elementSize;
         long destOffset = (long) destPos * elementSize;
-        if (src == dest && srcPos < destPos) { // bad aliased case
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (probability(NOT_FREQUENT_PROBABILITY, src == dest) && probability(NOT_FREQUENT_PROBABILITY, srcPos < destPos)) {
+            // bad aliased case
             for (long i = byteLength - elementSize; i >= byteLength - nonVectorBytes; i -= elementSize) {
                 UnsafeStoreNode.store(dest, header, i + destOffset, UnsafeLoadNode.load(src, header, i + srcOffset, baseKind), baseKind);
             }
@@ -107,7 +107,6 @@
 
     public static void checkNonNull(Object obj) {
         if (obj == null) {
-            probability(DEOPT_PATH_PROBABILITY);
             checkNPECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
@@ -116,7 +115,6 @@
     public static int checkArrayType(Word hub) {
         int layoutHelper = readLayoutHelper(hub);
         if (layoutHelper >= 0) {
-            probability(DEOPT_PATH_PROBABILITY);
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
         return layoutHelper;
@@ -124,27 +122,22 @@
 
     public static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) {
         if (srcPos < 0) {
-            probability(DEOPT_PATH_PROBABILITY);
             checkAIOOBECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
         if (destPos < 0) {
-            probability(DEOPT_PATH_PROBABILITY);
             checkAIOOBECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
         if (length < 0) {
-            probability(DEOPT_PATH_PROBABILITY);
             checkAIOOBECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
         if (srcPos + length > ArrayLengthNode.arrayLength(src)) {
-            probability(DEOPT_PATH_PROBABILITY);
             checkAIOOBECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
         if (destPos + length > ArrayLengthNode.arrayLength(dest)) {
-            probability(DEOPT_PATH_PROBABILITY);
             checkAIOOBECounter.inc();
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
@@ -278,13 +271,10 @@
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace()) == 0);
 
-        if (srcHub.equal(destHub) && src != dest) {
-            probability(FAST_PATH_PROBABILITY);
-
+        if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, src != dest)) {
             checkLimits(src, srcPos, dest, destPos, length);
-            if (isObjectArray) {
+            if (probability(FAST_PATH_PROBABILITY, isObjectArray)) {
                 genericObjectExactCallCounter.inc();
-                probability(FAST_PATH_PROBABILITY);
                 arrayObjectCopy(src, srcPos, dest, destPos, length);
             } else {
                 genericPrimitiveCallCounter.inc();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Fri Apr 26 18:38:56 2013 +0200
@@ -65,13 +65,11 @@
      */
     @Snippet
     public static Object checkcastExact(Object object, Word exactHub, @ConstantParameter boolean checkNull) {
-        if (checkNull && object == null) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
         } else {
             Word objectHub = loadHub(object);
             if (objectHub.notEqual(exactHub)) {
-                probability(DEOPT_PATH_PROBABILITY);
                 exactMiss.inc();
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
             }
@@ -92,13 +90,11 @@
      */
     @Snippet
     public static Object checkcastPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, @ConstantParameter boolean checkNull) {
-        if (checkNull && object == null) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
         } else {
             Word objectHub = loadHub(object);
             if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) {
-                probability(DEOPT_PATH_PROBABILITY);
                 displayMiss.inc();
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
             }
@@ -113,8 +109,7 @@
      */
     @Snippet
     public static Object checkcastSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @ConstantParameter boolean checkNull) {
-        if (checkNull && object == null) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
         } else {
             Word objectHub = loadHub(object);
@@ -142,8 +137,7 @@
      */
     @Snippet
     public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) {
-        if (checkNull && object == null) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
         } else {
             Word objectHub = loadHub(object);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java	Fri Apr 26 18:38:56 2013 +0200
@@ -644,11 +644,9 @@
 
         // this code is independent from biased locking (although it does not look that way)
         final Word biasedLock = mark.and(biasedLockMaskInPlace());
-        if (biasedLock.equal(Word.unsigned(unlockedMask()))) {
-            probability(FAST_PATH_PROBABILITY);
+        if (probability(FAST_PATH_PROBABILITY, biasedLock.equal(Word.unsigned(unlockedMask())))) {
             int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue();
-            if (hash != uninitializedIdentityHashCodeValue()) {
-                probability(FAST_PATH_PROBABILITY);
+            if (probability(FAST_PATH_PROBABILITY, hash != uninitializedIdentityHashCodeValue())) {
                 return hash;
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Apr 26 18:38:56 2013 +0200
@@ -58,14 +58,12 @@
      */
     @Snippet
     public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
-        if (checkNull && object == null) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
             return falseValue;
         }
         Word objectHub = loadHub(object);
-        if (objectHub.notEqual(exactHub)) {
-            probability(LIKELY_PROBABILITY);
+        if (probability(LIKELY_PROBABILITY, objectHub.notEqual(exactHub))) {
             exactMiss.inc();
             return falseValue;
         }
@@ -78,14 +76,12 @@
      */
     @Snippet
     public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
-        if (checkNull && object == null) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
             return falseValue;
         }
         Word objectHub = loadHub(object);
-        if (objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub)) {
-            probability(NOT_LIKELY_PROBABILITY);
+        if (probability(NOT_LIKELY_PROBABILITY, objectHub.readWord(superCheckOffset, FINAL_LOCATION).notEqual(hub))) {
             displayMiss.inc();
             return falseValue;
         }
@@ -99,8 +95,7 @@
     @Snippet
     public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue,
                     @ConstantParameter boolean checkNull) {
-        if (checkNull && object == null) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
             return falseValue;
         }
@@ -110,8 +105,7 @@
         for (int i = 0; i < hints.length; i++) {
             Word hintHub = hints[i];
             boolean positive = hintIsPositive[i];
-            if (hintHub.equal(objectHub)) {
-                probability(NOT_FREQUENT_PROBABILITY);
+            if (probability(NOT_FREQUENT_PROBABILITY, hintHub.equal(objectHub))) {
                 hintsHit.inc();
                 return positive ? trueValue : falseValue;
             }
@@ -127,8 +121,7 @@
      */
     @Snippet
     public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
-        if (checkNull && object == null) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
             return falseValue;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Apr 26 18:38:56 2013 +0200
@@ -102,10 +102,9 @@
             final Word biasableLockBits = mark.and(biasedLockMaskInPlace());
 
             // First check to see whether biasing is enabled for this object
-            if (biasableLockBits.notEqual(Word.unsigned(biasedLockPattern()))) {
+            if (probability(NOT_FREQUENT_PROBABILITY, biasableLockBits.notEqual(Word.unsigned(biasedLockPattern())))) {
                 // Biasing not enabled -> fall through to lightweight locking
             } else {
-                probability(FREQUENT_PROBABILITY);
                 // The bias pattern is present in the object's mark word. Need to check
                 // whether the bias owner and the epoch are both still current.
                 Word hub = loadHub(object);
@@ -115,9 +114,8 @@
                 trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord);
                 trace(trace, "           thread: 0x%016lx\n", thread);
                 trace(trace, "              tmp: 0x%016lx\n", tmp);
-                if (tmp.equal(0)) {
+                if (probability(FREQUENT_PROBABILITY, tmp.equal(0))) {
                     // Object is already biased to current thread -> done
-                    probability(FREQUENT_PROBABILITY);
                     traceObject(trace, "+lock{bias:existing}", object);
                     return;
                 }
@@ -131,8 +129,7 @@
                 // If the low three bits in the xor result aren't clear, that means
                 // the prototype header is no longer biasable and we have to revoke
                 // the bias on this object.
-                if (tmp.and(biasedLockMaskInPlace()).equal(0)) {
-                    probability(FREQUENT_PROBABILITY);
+                if (probability(FREQUENT_PROBABILITY, tmp.and(biasedLockMaskInPlace()).equal(0))) {
                     // Biasing is still enabled for object's type. See whether the
                     // epoch of the current bias is still valid, meaning that the epoch
                     // bits of the mark word are equal to the epoch bits of the
@@ -142,8 +139,7 @@
                     // that the current epoch is invalid in order to do this because
                     // otherwise the manipulations it performs on the mark word are
                     // illegal.
-                    if (tmp.and(epochMaskInPlace()).equal(0)) {
-                        probability(FREQUENT_PROBABILITY);
+                    if (probability(FREQUENT_PROBABILITY, tmp.and(epochMaskInPlace()).equal(0))) {
                         // The epoch of the current bias is still valid but we know nothing
                         // about the owner; it might be set or it might be clear. Try to
                         // acquire the bias of the object using an atomic operation. If this
@@ -154,7 +150,7 @@
                         Word biasedMark = unbiasedMark.or(thread);
                         trace(trace, "     unbiasedMark: 0x%016lx\n", unbiasedMark);
                         trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
-                        if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark)) {
+                        if (probability(VERY_FAST_DEOPT_PATH_PROBABILITY, compareAndSwap(object, markOffset(), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark))) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:acquired}", object);
                             return;
@@ -162,7 +158,6 @@
                         // If the biasing toward our thread failed, this means that another thread
                         // owns the bias and we need to revoke that bias. The revocation will occur
                         // in the interpreter runtime.
-                        probability(DEOPT_PATH_PROBABILITY);
                         traceObject(trace, "+lock{stub:revoke}", object);
                         MonitorEnterStubCall.call(object, lock);
                         return;
@@ -175,7 +170,7 @@
                         // the bias from one thread to another directly in this situation.
                         Word biasedMark = prototypeMarkWord.or(thread);
                         trace(trace, "       biasedMark: 0x%016lx\n", biasedMark);
-                        if (compareAndSwap(object, markOffset(), mark, biasedMark, MARK_WORD_LOCATION).equal(mark)) {
+                        if (probability(VERY_FAST_DEOPT_PATH_PROBABILITY, compareAndSwap(object, markOffset(), mark, biasedMark, MARK_WORD_LOCATION).equal(mark))) {
                             // Object is now biased to current thread -> done
                             traceObject(trace, "+lock{bias:transfer}", object);
                             return;
@@ -183,7 +178,6 @@
                         // If the biasing toward our thread failed, then another thread
                         // succeeded in biasing it toward itself and we need to revoke that
                         // bias. The revocation will occur in the runtime in the slow case.
-                        probability(DEOPT_PATH_PROBABILITY);
                         traceObject(trace, "+lock{stub:epoch-expired}", object);
                         MonitorEnterStubCall.call(object, lock);
                         return;
@@ -239,9 +233,8 @@
             // significant 2 bits cleared and page_size is a power of 2
             final Word alignedMask = Word.unsigned(wordSize() - 1);
             final Word stackPointer = stackPointer();
-            if (currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0)) {
+            if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) {
                 // Most likely not a recursive lock, go into a slow runtime call
-                probability(DEOPT_PATH_PROBABILITY);
                 traceObject(trace, "+lock{stub:failed-cas}", object);
                 MonitorEnterStubCall.call(object, lock);
                 return;
@@ -290,8 +283,7 @@
             // the bias bit would be clear.
             final Word mark = loadWordFromObject(object, markOffset());
             trace(trace, "             mark: 0x%016lx\n", mark);
-            if (mark.and(biasedLockMaskInPlace()).equal(Word.unsigned(biasedLockPattern()))) {
-                probability(FREQUENT_PROBABILITY);
+            if (probability(FREQUENT_PROBABILITY, mark.and(biasedLockMaskInPlace()).equal(Word.unsigned(biasedLockPattern())))) {
                 endLockScope();
                 decCounter();
                 traceObject(trace, "-lock{bias}", object);
@@ -313,10 +305,9 @@
             // Test if object's mark word is pointing to the displaced mark word, and if so, restore
             // the displaced mark in the object - if the object's mark word is not pointing to
             // the displaced mark word, do unlocking via runtime call.
-            if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock)) {
+            if (probability(VERY_SLOW_PATH_PROBABILITY, DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock))) {
                 // The object's mark word was not pointing to the displaced header,
                 // we do unlocking via runtime call.
-                probability(DEOPT_PATH_PROBABILITY);
                 traceObject(trace, "-lock{stub}", object);
                 MonitorExitStubCall.call(object);
             } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Apr 26 18:38:56 2013 +0200
@@ -64,8 +64,7 @@
          * this check might lead to problems if the TLAB is within 16GB of the address space end
          * (checked in c++ code)
          */
-        if (newTop.belowOrEqual(end)) {
-            probability(FAST_PATH_PROBABILITY);
+        if (probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) {
             writeTlabTop(thread, newTop);
             return top;
         }
@@ -76,11 +75,10 @@
     public static Object initializeObject(Word memory, Word hub, Word prototypeMarkWord, @ConstantParameter int size, @ConstantParameter boolean fillContents, @ConstantParameter boolean locked) {
 
         Object result;
-        if (memory.equal(0)) {
+        if (probability(SLOW_PATH_PROBABILITY, memory.equal(0))) {
             new_stub.inc();
             result = NewInstanceStubCall.call(hub);
         } else {
-            probability(FAST_PATH_PROBABILITY);
             if (locked) {
                 formatObject(hub, size, memory, thread().or(biasedLockPattern()), fillContents);
             } else {
@@ -108,11 +106,10 @@
 
     private static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, int headerSize, boolean fillContents) {
         Object result;
-        if (memory.equal(0)) {
+        if (probability(SLOW_PATH_PROBABILITY, memory.equal(0))) {
             newarray_stub.inc();
             result = NewArrayStubCall.call(hub, length);
         } else {
-            probability(FAST_PATH_PROBABILITY);
             newarray_loopInit.inc();
             formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents);
             result = memory.toObject();
@@ -130,7 +127,6 @@
     public static Object allocateArrayAndInitialize(int length, @ConstantParameter int alignment, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize,
                     @ConstantParameter boolean fillContents, @ConstantParameter ResolvedJavaType type) {
         if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) {
-            probability(DEOPT_PATH_PROBABILITY);
             // This handles both negative array sizes and very large array sizes
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Fri Apr 26 18:38:56 2013 +0200
@@ -84,7 +84,6 @@
     private static Word getAndCheckHub(Object src) {
         Word hub = loadHub(src);
         if (!(src instanceof Cloneable)) {
-            probability(DEOPT_PATH_PROBABILITY);
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
         return hub;
@@ -110,8 +109,7 @@
         genericCloneCounter.inc();
         Word hub = getAndCheckHub(src);
         int layoutHelper = hub.readInt(layoutHelperOffset(), FINAL_LOCATION);
-        if (layoutHelper < 0) {
-            probability(LIKELY_PROBABILITY);
+        if (probability(LIKELY_PROBABILITY, layoutHelper < 0)) {
             genericArrayCloneCounter.inc();
             return arrayClone(src, hub, layoutHelper);
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java	Fri Apr 26 18:38:56 2013 +0200
@@ -56,8 +56,7 @@
 
     @MethodSubstitution
     public static int identityHashCode(Object x) {
-        if (x == null) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (probability(NOT_FREQUENT_PROBABILITY, x == null)) {
             return 0;
         }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Fri Apr 26 18:38:56 2013 +0200
@@ -89,8 +89,7 @@
         Word secondarySupers = s.readWord(secondarySupersOffset(), SECONDARY_SUPERS_LOCATION);
         int length = secondarySupers.readInt(metaspaceArrayLengthOffset(), FINAL_LOCATION);
         for (int i = 0; i < length; i++) {
-            if (t.equal(loadSecondarySupersElement(secondarySupers, i))) {
-                probability(NOT_LIKELY_PROBABILITY);
+            if (probability(NOT_LIKELY_PROBABILITY, t.equal(loadSecondarySupersElement(secondarySupers, i)))) {
                 s.writeWord(secondarySuperCacheOffset(), t, SECONDARY_SUPER_CACHE_LOCATION);
                 secondariesHit.inc();
                 return true;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Apr 26 18:38:56 2013 +0200
@@ -34,7 +34,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.bytecode.*;
@@ -798,12 +797,7 @@
         if (!optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) {
             return null;
         } else {
-            ResolvedJavaType uniqueSubtype = type.findUniqueConcreteSubtype();
-            if (uniqueSubtype != null) {
-                return new JavaTypeProfile(profilingInfo.getNullSeen(bci()), 0.0D, new ProfiledType(uniqueSubtype, 1.0D));
-            } else {
-                return profilingInfo.getTypeProfile(bci());
-            }
+            return profilingInfo.getTypeProfile(bci());
         }
     }
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java	Fri Apr 26 18:38:56 2013 +0200
@@ -30,18 +30,19 @@
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 
 public class AMD64AddressValue extends CompositeValue {
 
     private static final long serialVersionUID = -4444600052487578694L;
 
-    @Component({REG, UNUSED}) protected AllocatableValue base;
-    @Component({REG, UNUSED}) protected AllocatableValue index;
+    @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue base;
+    @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue index;
     protected final Scale scale;
     protected final int displacement;
 
     public AMD64AddressValue(Kind kind, AllocatableValue base, int displacement) {
-        this(kind, base, AllocatableValue.UNUSED, Scale.Times1, displacement);
+        this(kind, base, Value.ILLEGAL, Scale.Times1, displacement);
     }
 
     public AMD64AddressValue(Kind kind, AllocatableValue base, AllocatableValue index, Scale scale, int displacement) {
@@ -53,7 +54,7 @@
     }
 
     private static Register toRegister(AllocatableValue value) {
-        if (value == AllocatableValue.UNUSED) {
+        if (value == Value.ILLEGAL) {
             return Register.None;
         } else {
             RegisterValue reg = (RegisterValue) value;
@@ -67,8 +68,7 @@
 
     @Override
     public String toString() {
-        StringBuilder s = new StringBuilder();
-        s.append(getKind().getJavaName()).append("[");
+        StringBuilder s = new StringBuilder("[");
         String sep = "";
         if (isLegal(base)) {
             s.append(base);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Fri Apr 26 18:38:56 2013 +0200
@@ -26,7 +26,6 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.amd64.*;
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.graph.*;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java	Fri Apr 26 18:38:56 2013 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.lir.amd64;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
 import com.oracle.graal.lir.asm.*;
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Fri Apr 26 18:38:56 2013 +0200
@@ -44,10 +44,10 @@
     @Opcode("MOVE")
     public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp {
 
-        @Def({REG, HINT}) protected Value result;
+        @Def({REG, HINT}) protected AllocatableValue result;
         @Use({REG, STACK, CONST}) protected Value input;
 
-        public MoveToRegOp(Value result, Value input) {
+        public MoveToRegOp(AllocatableValue result, Value input) {
             this.result = result;
             this.input = input;
         }
@@ -63,7 +63,7 @@
         }
 
         @Override
-        public Value getResult() {
+        public AllocatableValue getResult() {
             return result;
         }
     }
@@ -71,10 +71,10 @@
     @Opcode("MOVE")
     public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp {
 
-        @Def({REG, STACK}) protected Value result;
+        @Def({REG, STACK}) protected AllocatableValue result;
         @Use({REG, CONST, HINT}) protected Value input;
 
-        public MoveFromRegOp(Value result, Value input) {
+        public MoveFromRegOp(AllocatableValue result, Value input) {
             this.result = result;
             this.input = input;
         }
@@ -90,17 +90,19 @@
         }
 
         @Override
-        public Value getResult() {
+        public AllocatableValue getResult() {
             return result;
         }
     }
 
     public abstract static class MemOp extends AMD64LIRInstruction {
 
+        protected final Kind kind;
         @Use({COMPOSITE}) protected AMD64AddressValue address;
         @State protected LIRFrameState state;
 
-        public MemOp(AMD64AddressValue address, LIRFrameState state) {
+        public MemOp(Kind kind, AMD64AddressValue address, LIRFrameState state) {
+            this.kind = kind;
             this.address = address;
             this.state = state;
         }
@@ -120,14 +122,14 @@
 
         @Def({REG}) protected AllocatableValue result;
 
-        public LoadOp(AllocatableValue result, AMD64AddressValue address, LIRFrameState state) {
-            super(address, state);
+        public LoadOp(Kind kind, AllocatableValue result, AMD64AddressValue address, LIRFrameState state) {
+            super(kind, address, state);
             this.result = result;
         }
 
         @Override
         public void emitMemAccess(AMD64MacroAssembler masm) {
-            switch (address.getKind()) {
+            switch (kind) {
                 case Boolean:
                 case Byte:
                     masm.movsxb(asRegister(result), address.toAddress());
@@ -163,15 +165,15 @@
 
         @Use({REG}) protected AllocatableValue input;
 
-        public StoreOp(AMD64AddressValue address, AllocatableValue input, LIRFrameState state) {
-            super(address, state);
+        public StoreOp(Kind kind, AMD64AddressValue address, AllocatableValue input, LIRFrameState state) {
+            super(kind, address, state);
             this.input = input;
         }
 
         @Override
         public void emitMemAccess(AMD64MacroAssembler masm) {
             assert isRegister(input);
-            switch (address.getKind()) {
+            switch (kind) {
                 case Boolean:
                 case Byte:
                     masm.movb(address.toAddress(), asRegister(input));
@@ -205,14 +207,14 @@
 
         protected final Constant input;
 
-        public StoreConstantOp(AMD64AddressValue address, Constant input, LIRFrameState state) {
-            super(address, state);
+        public StoreConstantOp(Kind kind, AMD64AddressValue address, Constant input, LIRFrameState state) {
+            super(kind, address, state);
             this.input = input;
         }
 
         @Override
         public void emitMemAccess(AMD64MacroAssembler masm) {
-            switch (address.getKind()) {
+            switch (kind) {
                 case Boolean:
                 case Byte:
                     masm.movb(address.toAddress(), input.asInt() & 0xFF);
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java	Fri Apr 26 18:38:56 2013 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 
 /**
  * Represents an address in target machine memory, specified via some combination of a base register
@@ -38,7 +39,7 @@
 
     private static final long serialVersionUID = 1802222435353022623L;
 
-    @Component({REG, UNUSED}) private AllocatableValue base;
+    @Component({REG, OperandFlag.ILLEGAL}) private AllocatableValue base;
     private final long displacement;
 
     /**
@@ -68,7 +69,7 @@
     }
 
     public PTXAddress toAddress() {
-        Register baseReg = base == AllocatableValue.UNUSED ? Register.None : asRegister(base);
+        Register baseReg = base == Value.ILLEGAL ? Register.None : asRegister(base);
         return new PTXAddress(baseReg, displacement);
     }
 
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java	Fri Apr 26 18:38:56 2013 +0200
@@ -25,7 +25,6 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.ptx.*;
 import com.oracle.graal.graph.*;
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Fri Apr 26 18:38:56 2013 +0200
@@ -97,6 +97,7 @@
 
     @SuppressWarnings("unused")
     public static class CondMoveOp extends PTXLIRInstruction {
+
         @Def({REG, HINT}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Use({REG, STACK, CONST}) protected Value falseValue;
@@ -119,6 +120,7 @@
 
     @SuppressWarnings("unused")
     public static class FloatCondMoveOp extends PTXLIRInstruction {
+
         @Def({REG}) protected Value result;
         @Alive({REG}) protected Value trueValue;
         @Alive({REG}) protected Value falseValue;
@@ -142,14 +144,14 @@
     }
 
     public static class SequentialSwitchOp extends PTXLIRInstruction implements FallThroughOp {
+
         @Use({CONST}) protected Constant[] keyConstants;
         private final LabelRef[] keyTargets;
         private LabelRef defaultTarget;
         @Alive({REG}) protected Value key;
         @Temp({REG, ILLEGAL}) protected Value scratch;
 
-        public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget,
-                                  Value key, Value scratch) {
+        public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
             assert keyConstants.length == keyTargets.length;
             this.keyConstants = keyConstants;
             this.keyTargets = keyTargets;
@@ -216,14 +218,14 @@
     }
 
     public static class TableSwitchOp extends PTXLIRInstruction {
+
         private final int lowKey;
         private final LabelRef defaultTarget;
         private final LabelRef[] targets;
         @Alive protected Value index;
         @Temp protected Value scratch;
 
-        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets,
-                             Variable index, Variable scratch) {
+        public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) {
             this.lowKey = lowKey;
             this.defaultTarget = defaultTarget;
             this.targets = targets;
@@ -238,9 +240,7 @@
     }
 
     @SuppressWarnings("unused")
-    private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey,
-                                    LabelRef defaultTarget, LabelRef[] targets,
-                                    Register value, Register scratch) {
+    private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, Register value, Register scratch) {
         Buffer buf = masm.codeBuffer;
         // Compare index against jump table bounds
         int highKey = lowKey + targets.length - 1;
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java	Fri Apr 26 18:38:56 2013 +0200
@@ -39,10 +39,10 @@
     @Opcode("MOVE")
     public static class SpillMoveOp extends PTXLIRInstruction implements MoveOp {
 
-        @Def({REG, STACK}) protected Value result;
+        @Def({REG, STACK}) protected AllocatableValue result;
         @Use({REG, STACK, CONST}) protected Value input;
 
-        public SpillMoveOp(Value result, Value input) {
+        public SpillMoveOp(AllocatableValue result, Value input) {
             this.result = result;
             this.input = input;
         }
@@ -58,7 +58,7 @@
         }
 
         @Override
-        public Value getResult() {
+        public AllocatableValue getResult() {
             return result;
         }
     }
@@ -66,10 +66,10 @@
     @Opcode("MOVE")
     public static class MoveToRegOp extends PTXLIRInstruction implements MoveOp {
 
-        @Def({REG, HINT}) protected Value result;
+        @Def({REG, HINT}) protected AllocatableValue result;
         @Use({REG, STACK, CONST}) protected Value input;
 
-        public MoveToRegOp(Value result, Value input) {
+        public MoveToRegOp(AllocatableValue result, Value input) {
             this.result = result;
             this.input = input;
         }
@@ -85,7 +85,7 @@
         }
 
         @Override
-        public Value getResult() {
+        public AllocatableValue getResult() {
             return result;
         }
     }
@@ -93,10 +93,10 @@
     @Opcode("MOVE")
     public static class MoveFromRegOp extends PTXLIRInstruction implements MoveOp {
 
-        @Def({REG, STACK}) protected Value result;
+        @Def({REG, STACK}) protected AllocatableValue result;
         @Use({REG, CONST, HINT}) protected Value input;
 
-        public MoveFromRegOp(Value result, Value input) {
+        public MoveFromRegOp(AllocatableValue result, Value input) {
             this.result = result;
             this.input = input;
         }
@@ -112,18 +112,20 @@
         }
 
         @Override
-        public Value getResult() {
+        public AllocatableValue getResult() {
             return result;
         }
     }
 
     public static class LoadOp extends PTXLIRInstruction {
 
+        private final Kind kind;
         @Def({REG}) protected AllocatableValue result;
         @Use({COMPOSITE}) protected PTXAddressValue address;
         @State protected LIRFrameState state;
 
-        public LoadOp(AllocatableValue result, PTXAddressValue address, LIRFrameState state) {
+        public LoadOp(Kind kind, AllocatableValue result, PTXAddressValue address, LIRFrameState state) {
+            this.kind = kind;
             this.result = result;
             this.address = address;
             this.state = state;
@@ -132,7 +134,7 @@
         @Override
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
             PTXAddress addr = address.toAddress();
-            switch (address.getKind()) {
+            switch (kind) {
                 case Byte:
                     masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement());
                     break;
@@ -165,11 +167,13 @@
 
     public static class StoreOp extends PTXLIRInstruction {
 
+        private final Kind kind;
         @Use({COMPOSITE}) protected PTXAddressValue address;
         @Use({REG}) protected AllocatableValue input;
         @State protected LIRFrameState state;
 
-        public StoreOp(PTXAddressValue address, AllocatableValue input, LIRFrameState state) {
+        public StoreOp(Kind kind, PTXAddressValue address, AllocatableValue input, LIRFrameState state) {
+            this.kind = kind;
             this.address = address;
             this.input = input;
             this.state = state;
@@ -179,7 +183,7 @@
         public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) {
             assert isRegister(input);
             PTXAddress addr = address.toAddress();
-            switch (address.getKind()) {
+            switch (kind) {
                 case Byte:
                     masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input));
                     break;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Fri Apr 26 18:38:56 2013 +0200
@@ -64,7 +64,7 @@
 
     public interface SpillMoveFactory {
 
-        LIRInstruction createMove(Value result, Value input);
+        LIRInstruction createMove(AllocatableValue result, Value input);
     }
 
     private boolean hasArgInCallerFrame;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Fri Apr 26 18:38:56 2013 +0200
@@ -181,11 +181,6 @@
         ILLEGAL,
 
         /**
-         * The value can be {@link AllocatableValue#UNUSED}.
-         */
-        UNUSED,
-
-        /**
          * The register allocator should try to assign a certain register to improve code quality.
          * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints.
          */
@@ -205,10 +200,10 @@
 
     static {
         ALLOWED_FLAGS = new EnumMap<>(OperandMode.class);
-        ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNUSED, UNINITIALIZED));
-        ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNUSED, UNINITIALIZED));
-        ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, COMPOSITE, CONST, ILLEGAL, UNUSED, HINT));
-        ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, UNUSED, HINT));
+        ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED));
+        ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNINITIALIZED));
+        ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, COMPOSITE, CONST, ILLEGAL, HINT));
+        ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, HINT));
     }
 
     /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Fri Apr 26 18:38:56 2013 +0200
@@ -232,8 +232,7 @@
 
     private static Value allowed(Object op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
         if ((isVariable(value) && flags.contains(OperandFlag.REG)) || (isRegister(value) && flags.contains(OperandFlag.REG)) || (isStackSlot(value) && flags.contains(OperandFlag.STACK)) ||
-                        (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL)) ||
-                        (value == AllocatableValue.UNUSED && flags.contains(OperandFlag.UNUSED))) {
+                        (isConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) || (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) {
             return value;
         }
         TTY.println("instruction %s", op);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Apr 26 18:38:56 2013 +0200
@@ -117,7 +117,7 @@
 
         Value getInput();
 
-        Value getResult();
+        AllocatableValue getResult();
     }
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -91,18 +91,6 @@
         return getY().generateAddress(gen, xAddr);
     }
 
-    @Override
-    public Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting) {
-        Value xAddr = getX().generateAddress(gen, base);
-        return getY().generateLoad(gen, xAddr, deopting);
-    }
-
-    @Override
-    public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) {
-        Value xAddr = getX().generateAddress(gen, base);
-        getY().generateStore(gen, xAddr, value, deopting);
-    }
-
     @NodeIntrinsic
     public static native Location addLocation(@ConstantNodeParameter Object identity, @ConstantNodeParameter Kind kind, Location x, Location y);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -56,16 +55,6 @@
 
     @Override
     public Value generateAddress(LIRGeneratorTool gen, Value base) {
-        return gen.emitLea(base, displacement(), Value.ILLEGAL, 0);
-    }
-
-    @Override
-    public Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting) {
-        return gen.emitLoad(getValueKind(), base, displacement(), Value.ILLEGAL, 0, deopting);
-    }
-
-    @Override
-    public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) {
-        gen.emitStore(getValueKind(), base, displacement(), Value.ILLEGAL, 0, value, deopting);
+        return gen.emitAddress(base, displacement(), Value.ILLEGAL, 0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -53,7 +54,8 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, location().generateLoad(gen, gen.operand(object()), this));
+        Value address = location().generateAddress(gen, gen.operand(object()));
+        gen.setResult(this, gen.emitLoad(location().getValueKind(), address, this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -91,17 +91,7 @@
 
     @Override
     public Value generateAddress(LIRGeneratorTool gen, Value base) {
-        return gen.emitLea(base, displacement, gen.operand(index()), indexScaling());
-    }
-
-    @Override
-    public Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting) {
-        return gen.emitLoad(getValueKind(), base, displacement, gen.operand(index()), indexScaling(), deopting);
-    }
-
-    @Override
-    public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) {
-        gen.emitStore(getValueKind(), base, displacement, gen.operand(index()), indexScaling(), value, deopting);
+        return gen.emitAddress(base, displacement, gen.operand(index()), indexScaling());
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
-import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -100,8 +99,4 @@
     }
 
     public abstract Value generateAddress(LIRGeneratorTool gen, Value base);
-
-    public abstract Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting);
-
-    public abstract void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -57,7 +57,8 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, location().generateLoad(gen, gen.operand(object()), this));
+        Value address = location().generateAddress(gen, gen.operand(object()));
+        gen.setResult(this, gen.emitLoad(location().getValueKind(), address, this));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -91,7 +91,7 @@
     public void generate(LIRGeneratorTool generator) {
         if (kind() != object().kind()) {
             assert generator.target().sizeInBytes(kind()) == generator.target().sizeInBytes(object().kind()) : "unsafe cast cannot be used to change the size of a value";
-            Value result = generator.newVariable(kind());
+            AllocatableValue result = generator.newVariable(kind());
             generator.emitMove(result, generator.operand(object()));
             generator.setResult(this, result);
         } else {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.graph.*;
 
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}.
@@ -84,7 +85,8 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        location().generateStore(gen, gen.operand(object()), gen.operand(value()), this);
+        Value address = location().generateAddress(gen, gen.operand(object()));
+        gen.emitStore(location().getValueKind(), address, gen.operand(value()), this);
     }
 
     @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.java;
 
+import java.lang.reflect.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -102,6 +104,14 @@
         for (Node n : usages()) {
             assertTrue(n instanceof Invoke, "call target can only be used from an invoke (%s)", n);
         }
+        if (invokeKind == InvokeKind.Special || invokeKind == InvokeKind.Static) {
+            assertFalse(Modifier.isAbstract(targetMethod.getModifiers()), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod);
+        }
+        if (invokeKind == InvokeKind.Static) {
+            assertTrue(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for static methods (%s)", targetMethod);
+        } else {
+            assertFalse(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for non-static methods (%s)", targetMethod);
+        }
         return super.verify();
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Fri Apr 26 18:38:56 2013 +0200
@@ -29,11 +29,11 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 
-public abstract class LIRGeneratorTool {
+public interface LIRGeneratorTool {
 
-    public abstract TargetDescription target();
+    TargetDescription target();
 
-    public abstract CodeCacheProvider getRuntime();
+    CodeCacheProvider getRuntime();
 
     /**
      * Checks whether the supplied constant can be used without loading it into a register for most
@@ -43,100 +43,99 @@
      * @return True if the constant can be used directly, false if the constant needs to be in a
      *         register.
      */
-    public abstract boolean canInlineConstant(Constant c);
+    boolean canInlineConstant(Constant c);
 
-    public abstract RegisterAttributes attributes(Register register);
+    RegisterAttributes attributes(Register register);
 
-    public abstract Value operand(ValueNode object);
+    Value operand(ValueNode object);
 
-    public abstract AllocatableValue newVariable(Kind kind);
+    AllocatableValue newVariable(Kind kind);
 
-    public abstract Value setResult(ValueNode x, Value operand);
+    Value setResult(ValueNode x, Value operand);
 
-    public abstract Value emitMove(Value input);
+    AllocatableValue emitMove(Value input);
 
-    public abstract void emitMove(Value dst, Value src);
+    void emitMove(AllocatableValue dst, Value src);
 
-    public abstract Value emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode deopting);
+    Value emitAddress(Value base, long displacement, Value index, int scale);
 
-    public abstract void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value input, DeoptimizingNode deopting);
+    Value emitAddress(StackSlot slot);
 
-    public abstract Value emitLea(Value base, long displacement, Value index, int scale);
+    Value emitLoad(Kind kind, Value address, DeoptimizingNode deopting);
 
-    public abstract Value emitLea(StackSlot slot);
+    void emitStore(Kind kind, Value address, Value input, DeoptimizingNode deopting);
 
-    public abstract Value emitNegate(Value input);
+    Value emitNegate(Value input);
 
-    public abstract Value emitAdd(Value a, Value b);
+    Value emitAdd(Value a, Value b);
 
-    public abstract Value emitSub(Value a, Value b);
+    Value emitSub(Value a, Value b);
 
-    public abstract Value emitMul(Value a, Value b);
+    Value emitMul(Value a, Value b);
 
-    public abstract Value emitDiv(Value a, Value b, DeoptimizingNode deopting);
+    Value emitDiv(Value a, Value b, DeoptimizingNode deopting);
 
-    public abstract Value emitRem(Value a, Value b, DeoptimizingNode deopting);
+    Value emitRem(Value a, Value b, DeoptimizingNode deopting);
 
-    public abstract Value emitUDiv(Value a, Value b, DeoptimizingNode deopting);
+    Value emitUDiv(Value a, Value b, DeoptimizingNode deopting);
 
-    public abstract Value emitURem(Value a, Value b, DeoptimizingNode deopting);
+    Value emitURem(Value a, Value b, DeoptimizingNode deopting);
 
-    public abstract Value emitAnd(Value a, Value b);
+    Value emitAnd(Value a, Value b);
 
-    public abstract Value emitOr(Value a, Value b);
+    Value emitOr(Value a, Value b);
 
-    public abstract Value emitXor(Value a, Value b);
+    Value emitXor(Value a, Value b);
 
-    public abstract Value emitShl(Value a, Value b);
+    Value emitShl(Value a, Value b);
 
-    public abstract Value emitShr(Value a, Value b);
+    Value emitShr(Value a, Value b);
 
-    public abstract Value emitUShr(Value a, Value b);
+    Value emitUShr(Value a, Value b);
 
-    public abstract Value emitConvert(ConvertNode.Op opcode, Value inputVal);
+    Value emitConvert(ConvertNode.Op opcode, Value inputVal);
 
-    public abstract void emitMembar(int barriers);
+    void emitMembar(int barriers);
 
-    public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting);
+    void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting);
 
-    public abstract void emitNullCheck(ValueNode v, DeoptimizingNode deopting);
+    void emitNullCheck(ValueNode v, DeoptimizingNode deopting);
 
-    public abstract Value emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args);
+    Value emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args);
 
-    public abstract void emitIf(IfNode i);
+    void emitIf(IfNode i);
 
-    public abstract void emitConditional(ConditionalNode i);
+    void emitConditional(ConditionalNode i);
 
-    public abstract void emitSwitch(SwitchNode i);
+    void emitSwitch(SwitchNode i);
 
-    public abstract void emitInvoke(Invoke i);
+    void emitInvoke(Invoke i);
 
-    public abstract void visitRuntimeCall(RuntimeCallNode i);
+    void visitRuntimeCall(RuntimeCallNode i);
 
     // Handling of block-end nodes still needs to be unified in the LIRGenerator.
-    public abstract void visitMerge(MergeNode i);
+    void visitMerge(MergeNode i);
 
-    public abstract void visitEndNode(EndNode i);
+    void visitEndNode(EndNode i);
 
-    public abstract void visitLoopEnd(LoopEndNode i);
+    void visitLoopEnd(LoopEndNode i);
 
-    public abstract void visitCompareAndSwap(CompareAndSwapNode i);
+    void visitCompareAndSwap(CompareAndSwapNode i);
 
     // These methods define the contract a runtime specific backend must provide.
 
-    public abstract void visitReturn(ReturnNode i);
+    void visitReturn(ReturnNode i);
 
-    public abstract void visitSafepointNode(SafepointNode i);
+    void visitSafepointNode(SafepointNode i);
 
-    public abstract void visitBreakpointNode(BreakpointNode i);
+    void visitBreakpointNode(BreakpointNode i);
 
-    public abstract void emitUnwind(Value operand);
+    void emitUnwind(Value operand);
 
     /**
      * Called just before register allocation is performed on the LIR owned by this generator.
      */
-    public void beforeRegisterAllocation() {
-    }
+    void beforeRegisterAllocation();
 
-    public abstract void visitInfopointNode(InfopointNode i);
+    void visitInfopointNode(InfopointNode i);
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Apr 26 18:38:56 2013 +0200
@@ -254,6 +254,10 @@
             Class<? extends FixedWithNextNode> macroNodeClass = getMacroNodeClass(replacements, concrete);
             StructuredGraph graph = (StructuredGraph) invoke.asNode().graph();
             if (macroNodeClass != null) {
+                if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() != concrete) {
+                    assert ((MethodCallTargetNode) invoke.callTarget()).invokeKind() != InvokeKind.Static;
+                    InliningUtil.replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete);
+                }
                 FixedWithNextNode macroNode;
                 try {
                     macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke);
@@ -294,12 +298,12 @@
                 }
             });
         }
+    }
 
-        protected void replaceInvokeCallTarget(StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) {
-            MethodCallTargetNode oldCallTarget = (MethodCallTargetNode) invoke.callTarget();
-            MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType()));
-            invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget);
-        }
+    public static void replaceInvokeCallTarget(Invoke invoke, StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) {
+        MethodCallTargetNode oldCallTarget = (MethodCallTargetNode) invoke.callTarget();
+        MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType()));
+        invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget);
     }
 
     /**
@@ -378,7 +382,7 @@
         @Override
         public void tryToDevirtualizeInvoke(StructuredGraph graph, MetaAccessProvider runtime, Assumptions assumptions) {
             createGuard(graph, runtime);
-            replaceInvokeCallTarget(graph, InvokeKind.Special, concrete);
+            replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete);
         }
 
         private void createGuard(StructuredGraph graph, MetaAccessProvider runtime) {
@@ -730,7 +734,7 @@
             ValueNode receiver = ((MethodCallTargetNode) invoke.callTarget()).receiver();
             PiNode anchoredReceiver = createAnchoredReceiver(graph, invocationEntry, target.getDeclaringClass(), receiver, false);
             invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
-            replaceInvokeCallTarget(graph, kind, target);
+            replaceInvokeCallTarget(invoke, graph, kind, target);
         }
 
         private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) {
@@ -775,15 +779,13 @@
         @Override
         public void inline(StructuredGraph graph, MetaAccessProvider runtime, Replacements replacements, InliningCallback callback, Assumptions assumptions) {
             assumptions.record(takenAssumption);
-            Debug.log("recording assumption: %s", takenAssumption);
-
             super.inline(graph, runtime, replacements, callback, assumptions);
         }
 
         @Override
         public void tryToDevirtualizeInvoke(StructuredGraph graph, MetaAccessProvider runtime, Assumptions assumptions) {
             assumptions.record(takenAssumption);
-            replaceInvokeCallTarget(graph, InvokeKind.Special, concrete);
+            replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete);
         }
 
         @Override
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Fri Apr 26 18:38:56 2013 +0200
@@ -57,8 +57,7 @@
      */
     @Snippet
     public static int f2i(float input, int result) {
-        if (result == Integer.MIN_VALUE) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (probability(SLOW_PATH_PROBABILITY, result == Integer.MIN_VALUE)) {
             if (Float.isNaN(input)) {
                 // input is NaN -> return 0
                 return 0;
@@ -83,8 +82,7 @@
      */
     @Snippet
     public static long f2l(float input, long result) {
-        if (result == Long.MIN_VALUE) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (probability(SLOW_PATH_PROBABILITY, result == Long.MIN_VALUE)) {
             if (Float.isNaN(input)) {
                 // input is NaN -> return 0
                 return 0;
@@ -109,8 +107,7 @@
      */
     @Snippet
     public static int d2i(double input, int result) {
-        if (result == Integer.MIN_VALUE) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (probability(SLOW_PATH_PROBABILITY, result == Integer.MIN_VALUE)) {
             if (Double.isNaN(input)) {
                 // input is NaN -> return 0
                 return 0;
@@ -135,8 +132,7 @@
      */
     @Snippet
     public static long d2l(double input, long result) {
-        if (result == Long.MIN_VALUE) {
-            probability(NOT_FREQUENT_PROBABILITY);
+        if (probability(SLOW_PATH_PROBABILITY, result == Long.MIN_VALUE)) {
             if (Double.isNaN(input)) {
                 // input is NaN -> return 0
                 return 0;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationVerificationPhase.java	Fri Apr 26 18:38:56 2013 +0200
@@ -24,20 +24,20 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.Fold;
 
 /**
  * Checks that a graph contains no calls to {@link NodeIntrinsic} or {@link Fold} methods.
  */
 public class NodeIntrinsificationVerificationPhase extends Phase {
 
-    public static boolean verify(StructuredGraph graph) {
+    public static void verify(StructuredGraph graph) {
         new NodeIntrinsificationVerificationPhase().apply(graph);
-        return true;
     }
 
     @Override
@@ -49,11 +49,17 @@
 
     private static void checkInvoke(MethodCallTargetNode n) {
         ResolvedJavaMethod target = n.targetMethod();
-        NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class);
-        if (intrinsic != null) {
-            throw new GraalInternalError("Illegal call to node intrinsic in " + n.graph() + ": " + n.invoke());
+        if (target.getAnnotation(Node.NodeIntrinsic.class) != null) {
+            error(n, "Intrinsification");
         } else if (target.getAnnotation(Fold.class) != null) {
-            throw new GraalInternalError("Illegal call to foldable method in " + n.graph() + ": " + n.invoke());
+            error(n, "Folding");
         }
     }
+
+    private static void error(MethodCallTargetNode n, String failedAction) throws GraalInternalError {
+        String context = MetaUtil.format("%H.%n", ((StructuredGraph) n.graph()).method());
+        String target = n.invoke().callTarget().targetName();
+        throw new GraalInternalError(failedAction + " of call to '" + target + "' in '" + context + "' failed, most likely due to a parameter annotated with @" +
+                        ConstantNodeParameter.class.getSimpleName() + " not being resolvable to a constant during compilation");
+    }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Apr 26 18:38:56 2013 +0200
@@ -279,7 +279,10 @@
          */
         protected void finalizeGraph(StructuredGraph graph) {
             new NodeIntrinsificationPhase(runtime).apply(graph);
-            assert SnippetTemplate.hasConstantParameter(method) || NodeIntrinsificationVerificationPhase.verify(graph);
+            if (!SnippetTemplate.hasConstantParameter(method)) {
+                NodeIntrinsificationVerificationPhase.verify(graph);
+            }
+            new ConvertDeoptimizeToGuardPhase().apply(graph);
 
             if (original == null) {
                 new SnippetFrameStateCleanupPhase().apply(graph);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Fri Apr 26 18:38:56 2013 +0200
@@ -378,7 +378,7 @@
 
             new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), 0, null).apply(snippetCopy);
         }
-        assert NodeIntrinsificationVerificationPhase.verify(snippetCopy);
+        NodeIntrinsificationVerificationPhase.verify(snippetCopy);
 
         // Gather the template parameters
         parameters = new Object[parameterCount];
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -22,17 +22,17 @@
  */
 package com.oracle.graal.replacements.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
 
 /**
  * Instances of this node class will look for a preceding if node and put the given probability into
  * the if node's taken probability. Then the branch probability node will be removed. This node is
  * intended primarily for snippets, so that they can define their fast and slow paths.
  */
-public class BranchProbabilityNode extends FixedWithNextNode implements Simplifiable {
+public class BranchProbabilityNode extends FloatingNode implements Canonicalizable, Lowerable {
 
     public static final double LIKELY_PROBABILITY = 0.6;
     public static final double NOT_LIKELY_PROBABILITY = 1 - LIKELY_PROBABILITY;
@@ -43,41 +43,80 @@
     public static final double FAST_PATH_PROBABILITY = 0.99;
     public static final double SLOW_PATH_PROBABILITY = 1 - FAST_PATH_PROBABILITY;
 
-    public static final double NOT_DEOPT_PATH_PROBABILITY = 0.999;
-    public static final double DEOPT_PATH_PROBABILITY = 1 - NOT_DEOPT_PATH_PROBABILITY;
+    public static final double VERY_FAST_DEOPT_PATH_PROBABILITY = 0.999;
+    public static final double VERY_SLOW_PATH_PROBABILITY = 1 - VERY_FAST_DEOPT_PATH_PROBABILITY;
 
-    private final double probability;
+    @Input private ValueNode probability;
+    @Input private ValueNode condition;
 
-    public BranchProbabilityNode(double probability) {
-        super(StampFactory.forVoid());
-        assert probability >= 0 && probability <= 1;
+    public BranchProbabilityNode(ValueNode probability, ValueNode condition) {
+        super(condition.stamp());
         this.probability = probability;
+        this.condition = condition;
+    }
+
+    public ValueNode getProbability() {
+        return probability;
+    }
+
+    public ValueNode getCondition() {
+        return condition;
     }
 
     @Override
-    public void simplify(SimplifierTool tool) {
-        FixedNode current = this;
-        while (!(current instanceof BeginNode)) {
-            current = (FixedNode) current.predecessor();
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (probability.isConstant()) {
+            double probabilityValue = probability.asConstant().asDouble();
+            if (probabilityValue < 0.0) {
+                throw new GraalInternalError("A negative probability of " + probabilityValue + " is not allowed!");
+            } else if (probabilityValue > 1.0) {
+                throw new GraalInternalError("A probability of more than 1.0 (" + probabilityValue + ") is not allowed!");
+            }
+            boolean couldSet = false;
+            for (IntegerEqualsNode node : this.usages().filter(IntegerEqualsNode.class)) {
+                if (node.condition() == Condition.EQ) {
+                    ValueNode other = node.x();
+                    if (node.x() == this) {
+                        other = node.y();
+                    }
+                    if (other.isConstant()) {
+                        double probabilityToSet = probabilityValue;
+                        if (other.asConstant().asInt() == 0) {
+                            probabilityToSet = 1.0 - probabilityToSet;
+                        }
+                        for (IfNode ifNodeUsages : node.usages().filter(IfNode.class)) {
+                            couldSet = true;
+                            ifNodeUsages.setTrueSuccessorProbability(probabilityToSet);
+                        }
+                    }
+                }
+            }
+            if (!couldSet) {
+                throw new GraalInternalError("Wrong usage of branch probability injection!");
+            }
+            return condition;
         }
-        BeginNode begin = (BeginNode) current;
-        assert begin.predecessor() instanceof IfNode : "explicit branch probability cannot follow a merge, only if nodes";
-        IfNode ifNode = (IfNode) begin.predecessor();
-        if (ifNode.trueSuccessor() == begin) {
-            ifNode.setTrueSuccessorProbability(probability);
-        } else {
-            ifNode.setTrueSuccessorProbability(1 - probability);
-        }
-
-        FixedNode next = next();
-        setNext(null);
-        ((FixedWithNextNode) predecessor()).setNext(next);
-        GraphUtil.killCFG(this);
+        return this;
     }
 
-    @SuppressWarnings("unused")
+    /**
+     * This intrinsic should only be used for the condition of an if statement. The parameter
+     * condition should also only denote a simple condition and not a combined condition involving
+     * && or || operators. It injects the probability of the condition into the if statement.
+     * 
+     * @param probability the probability that the given condition is true as a double value between
+     *            0.0 and 1.0.
+     * @param condition the simple condition without any && or || operators
+     * @return the condition
+     */
     @NodeIntrinsic
-    public static void probability(@ConstantNodeParameter double probability) {
+    public static boolean probability(double probability, boolean condition) {
+        assert probability >= 0.0 && probability <= 1.0;
+        return condition;
     }
 
+    @Override
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        throw new GraalInternalError("Branch probability could not be injected, because the probability value did not reduce to a constant value.");
+    }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectReadNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -47,7 +47,7 @@
 
     @Override
     public void generate(LIRGeneratorTool gen) {
-        gen.setResult(this, gen.emitLoad(readKind, gen.operand(address), 0, Value.ILLEGAL, 0, null));
+        gen.setResult(this, gen.emitLoad(readKind, gen.operand(address), null));
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectStoreNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -50,7 +50,7 @@
     @Override
     public void generate(LIRGeneratorTool gen) {
         Value v = gen.operand(value);
-        gen.emitStore(kind, gen.operand(address), 0, Value.ILLEGAL, 0, v, null);
+        gen.emitStore(kind, gen.operand(address), v, null);
     }
 
     /*
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -71,6 +71,7 @@
         StructuredGraph snippetGraph = getSnippetGraph(tool);
 
         InvokeNode invoke = replaceWithInvoke();
+        assert invoke.verify();
 
         if (snippetGraph != null) {
             InliningUtil.inline(invoke, snippetGraph, false);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/WriteRegisterNode.java	Fri Apr 26 18:38:56 2013 +0200
@@ -54,7 +54,7 @@
     @Override
     public void generate(LIRGeneratorTool generator) {
         Value val = generator.operand(value);
-        generator.emitMove(val, register.asValue(val.getKind()));
+        generator.emitMove(register.asValue(val.getKind()), val);
     }
 
     @Override
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Fri Apr 26 18:38:56 2013 +0200
@@ -34,7 +34,7 @@
  * <p>
  * Dynamically typed languages can speculate on the type of a frame slot and only fall back at run
  * time to a more generic type if necessary. The new type of a frame slot can be set using the
- * {@link FrameSlot#setType(Class)} method.
+ * {@link FrameSlot#setKind(FrameSlotKind)} method.
  * </p>
  * 
  * <p>
@@ -48,13 +48,13 @@
     public void test() {
         TruffleRuntime runtime = Truffle.getRuntime();
         FrameDescriptor frameDescriptor = new FrameDescriptor();
-        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", int.class);
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int);
         TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
         CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
-        Assert.assertEquals(int.class, slot.getType());
+        Assert.assertEquals(FrameSlotKind.Int, slot.getKind());
         Object result = target.call();
         Assert.assertEquals("42", result);
-        Assert.assertEquals(Object.class, slot.getType());
+        Assert.assertEquals(FrameSlotKind.Object, slot.getKind());
     }
 
     class TestRootNode extends RootNode {
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Fri Apr 26 18:38:56 2013 +0200
@@ -35,9 +35,9 @@
  * The frame is the preferred data structure for passing values between nodes. It can in particular
  * be used for storing the values of local variables of the guest language. The
  * {@link FrameDescriptor} represents the current structure of the frame. The method
- * {@link FrameDescriptor#addFrameSlot(Object, Class)} can be used to create predefined frame slots.
- * The setter and getter methods in the {@link Frame} class can be used to access the current value
- * of a particular frame slot.
+ * {@link FrameDescriptor#addFrameSlot(Object, FrameSlotKind)} can be used to create predefined
+ * frame slots. The setter and getter methods in the {@link Frame} class can be used to access the
+ * current value of a particular frame slot.
  * </p>
  * 
  * <p>
@@ -64,7 +64,7 @@
     public void test() {
         TruffleRuntime runtime = Truffle.getRuntime();
         FrameDescriptor frameDescriptor = new FrameDescriptor();
-        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", int.class);
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int);
         TestRootNode rootNode = new TestRootNode(new AssignLocal(slot), new ReadLocal(slot));
         CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
         Object result = target.call();
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Fri Apr 26 18:38:56 2013 +0200
@@ -47,13 +47,13 @@
     public void test() {
         TruffleRuntime runtime = Truffle.getRuntime();
         FrameDescriptor frameDescriptor = new FrameDescriptor();
-        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", int.class);
+        FrameSlot slot = frameDescriptor.addFrameSlot("localVar", FrameSlotKind.Int);
         TestRootNode rootNode = new TestRootNode(new IntAssignLocal(slot, new StringTestChildNode()), new IntReadLocal(slot));
         CallTarget target = runtime.createCallTarget(rootNode, frameDescriptor);
-        Assert.assertEquals(int.class, slot.getType());
+        Assert.assertEquals(FrameSlotKind.Int, slot.getKind());
         Object result = target.call();
         Assert.assertEquals("42", result);
-        Assert.assertEquals(Object.class, slot.getType());
+        Assert.assertEquals(FrameSlotKind.Object, slot.getKind());
     }
 
     class TestRootNode extends RootNode {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Fri Apr 26 18:38:56 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.api;
 
+import java.lang.annotation.*;
 import java.util.concurrent.*;
 
 /**
@@ -30,7 +31,11 @@
  */
 public class CompilerDirectives {
 
-    private static final double SLOWPATH_PROBABILITY = 0.0001;
+    public static final double LIKELY_PROBABILITY = 0.75;
+    public static final double UNLIKELY_PROBABILITY = 1.0 - LIKELY_PROBABILITY;
+
+    public static final double SLOWPATH_PROBABILITY = 0.0001;
+    public static final double FASTPATH_PROBABILITY = 1.0 - SLOWPATH_PROBABILITY;
 
     /**
      * Directive for the compiler to discontinue compilation at this code position and instead
@@ -62,20 +67,38 @@
     }
 
     /**
-     * Directive for the compiler that the current path has a very low probability to be executed.
-     */
-    public static void slowpath() {
-        injectBranchProbability(SLOWPATH_PROBABILITY);
-    }
-
-    /**
-     * Injects a probability for the current path into the probability information of the
-     * immediately preceeding branch instruction.
+     * Injects a probability for the given condition into the probability information of the
+     * immediately succeeding branch instruction for the condition. The probability must be a value
+     * between 0.0 and 1.0 (inclusive). The condition should not be a combined condition.
+     * 
+     * Example usage immediately before an if statement (it specifies that the likelihood for a to
+     * be greater than b is 90%):
+     * 
+     * <code>
+     * if (injectBranchProbability(0.9, a > b)) {
+     *    // ...
+     * }
+     * </code>
+     * 
+     * Example usage for a combined condition (it specifies that the likelihood for a to be greater
+     * than b is 90% and under the assumption that this is true, the likelihood for a being 0 is
+     * 10%):
+     * 
+     * <code>
+     * if (injectBranchProbability(0.9, a > b) && injectBranchProbability(0.1, a == 0)) {
+     *    // ...
+     * }
+     * </code>
+     * 
+     * There are predefined constants for commonly used probabilities (see
+     * {@link #LIKELY_PROBABILITY} , {@link #UNLIKELY_PROBABILITY}, {@link #SLOWPATH_PROBABILITY},
+     * {@link #FASTPATH_PROBABILITY} ).
      * 
      * @param probability the probability value between 0.0 and 1.0 that should be injected
      */
-    public static void injectBranchProbability(double probability) {
+    public static boolean injectBranchProbability(double probability, boolean condition) {
         assert probability >= 0.0 && probability <= 1.0;
+        return condition;
     }
 
     /**
@@ -85,4 +108,13 @@
      */
     public static void bailout(String reason) {
     }
+
+    /**
+     * Marks fields that should be considered final for a Truffle compilation although they are not
+     * final while executing in the interpreter.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD})
+    public @interface CompilationFinal {
+    }
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Fri Apr 26 18:38:56 2013 +0200
@@ -53,9 +53,9 @@
         return addFrameSlot(identifier, null);
     }
 
-    public FrameSlot addFrameSlot(Object identifier, Class<?> type) {
+    public FrameSlot addFrameSlot(Object identifier, FrameSlotKind kind) {
         assert !identifierToSlotMap.containsKey(identifier);
-        FrameSlotImpl slot = new FrameSlotImpl(this, identifier, slots.size(), type);
+        FrameSlotImpl slot = new FrameSlotImpl(this, identifier, slots.size(), kind);
         slots.add(slot);
         identifierToSlotMap.put(identifier, slot);
         updateVersion();
@@ -74,12 +74,12 @@
         return addFrameSlot(identifier);
     }
 
-    public FrameSlot findOrAddFrameSlot(Object identifier, Class<?> type) {
+    public FrameSlot findOrAddFrameSlot(Object identifier, FrameSlotKind kind) {
         FrameSlot result = findFrameSlot(identifier);
         if (result != null) {
             return result;
         }
-        return addFrameSlot(identifier, type);
+        return addFrameSlot(identifier, kind);
     }
 
     public int getSize() {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Fri Apr 26 18:38:56 2013 +0200
@@ -31,9 +31,9 @@
 
     int getIndex();
 
-    Class<?> getType();
+    FrameSlotKind getKind();
 
-    void setType(Class<?> type);
+    void setKind(FrameSlotKind kind);
 
     FrameDescriptor getFrameDescriptor();
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java	Fri Apr 26 18:38:56 2013 +0200
@@ -27,13 +27,13 @@
     private final FrameDescriptor descriptor;
     private final Object identifier;
     private final int index;
-    private Class<?> type;
+    private FrameSlotKind kind;
 
-    protected FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, Class<?> type) {
+    protected FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, FrameSlotKind kind) {
         this.descriptor = descriptor;
         this.identifier = identifier;
         this.index = index;
-        this.type = type;
+        this.kind = kind;
     }
 
     public Object getIdentifier() {
@@ -44,19 +44,19 @@
         return index;
     }
 
-    public Class<?> getType() {
-        return type;
+    public FrameSlotKind getKind() {
+        return kind;
     }
 
-    public void setType(final Class<?> type) {
-        assert this.type != type;
-        this.type = type;
+    public void setKind(final FrameSlotKind kind) {
+        assert this.kind != kind;
+        this.kind = kind;
         this.descriptor.updateVersion();
     }
 
     @Override
     public String toString() {
-        return "[" + index + "," + identifier + "," + type + "]";
+        return "[" + index + "," + identifier + "," + kind + "]";
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotKind.java	Fri Apr 26 18:38:56 2013 +0200
@@ -0,0 +1,27 @@
+/*
+ * 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.truffle.api.frame;
+
+public enum FrameSlotKind {
+    Illegal, Object, Long, Int, Double, Float, Boolean;
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java	Fri Apr 26 18:38:56 2013 +0200
@@ -33,8 +33,8 @@
      * @param value the new value of the local variable
      */
     public static void setObjectSafe(Frame frame, FrameSlot slot, Object value) {
-        if (slot.getType() != Object.class) {
-            slot.setType(Object.class);
+        if (slot.getKind() != FrameSlotKind.Object) {
+            slot.setKind(FrameSlotKind.Object);
         }
         try {
             frame.setObject(slot, value);
@@ -52,8 +52,8 @@
      * @param value the new value of the local variable
      */
     public static void setBooleanSafe(Frame frame, FrameSlot slot, boolean value) {
-        if (slot.getType() != boolean.class) {
-            slot.setType(boolean.class);
+        if (slot.getKind() != FrameSlotKind.Boolean) {
+            slot.setKind(FrameSlotKind.Boolean);
         }
         try {
             frame.setBoolean(slot, value);
@@ -71,8 +71,8 @@
      * @param value the new value of the local variable
      */
     public static void setIntSafe(Frame frame, FrameSlot slot, int value) {
-        if (slot.getType() != int.class) {
-            slot.setType(int.class);
+        if (slot.getKind() != FrameSlotKind.Int) {
+            slot.setKind(FrameSlotKind.Int);
         }
         try {
             frame.setInt(slot, value);
@@ -90,8 +90,8 @@
      * @param value the new value of the local variable
      */
     public static void setLongSafe(Frame frame, FrameSlot slot, long value) {
-        if (slot.getType() != long.class) {
-            slot.setType(long.class);
+        if (slot.getKind() != FrameSlotKind.Long) {
+            slot.setKind(FrameSlotKind.Long);
         }
         try {
             frame.setLong(slot, value);
@@ -109,8 +109,8 @@
      * @param value the new value of the local variable
      */
     public static void setFloatSafe(Frame frame, FrameSlot slot, float value) {
-        if (slot.getType() != float.class) {
-            slot.setType(float.class);
+        if (slot.getKind() != FrameSlotKind.Float) {
+            slot.setKind(FrameSlotKind.Float);
         }
         try {
             frame.setFloat(slot, value);
@@ -128,8 +128,8 @@
      * @param value the new value of the local variable
      */
     public static void setDoubleSafe(Frame frame, FrameSlot slot, double value) {
-        if (slot.getType() != double.class) {
-            slot.setType(double.class);
+        if (slot.getKind() != FrameSlotKind.Double) {
+            slot.setKind(FrameSlotKind.Double);
         }
         try {
             frame.setDouble(slot, value);
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Fri Apr 26 18:38:56 2013 +0200
@@ -33,14 +33,14 @@
     private final PackedFrame caller;
     private final Arguments arguments;
     private Object[] locals;
-    private Class[] tags;
+    private byte[] tags;
 
     public DefaultVirtualFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) {
         this.descriptor = descriptor;
         this.caller = caller;
         this.arguments = arguments;
         this.locals = new Object[descriptor.getSize()];
-        this.tags = new Class[descriptor.getSize()];
+        this.tags = new byte[descriptor.getSize()];
     }
 
     @Override
@@ -65,73 +65,73 @@
 
     @Override
     public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, Object.class);
+        verifyGet(slot, FrameSlotKind.Object);
         return locals[slot.getIndex()];
     }
 
     @Override
     public void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException {
-        verifySet(slot, Object.class);
+        verifySet(slot, FrameSlotKind.Object);
         locals[slot.getIndex()] = value;
     }
 
     @Override
     public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, boolean.class);
+        verifyGet(slot, FrameSlotKind.Boolean);
         return (boolean) locals[slot.getIndex()];
     }
 
     @Override
     public void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException {
-        verifySet(slot, boolean.class);
+        verifySet(slot, FrameSlotKind.Boolean);
         locals[slot.getIndex()] = value;
     }
 
     @Override
     public int getInt(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, int.class);
+        verifyGet(slot, FrameSlotKind.Int);
         return (int) locals[slot.getIndex()];
     }
 
     @Override
     public void setInt(FrameSlot slot, int value) throws FrameSlotTypeException {
-        verifySet(slot, int.class);
+        verifySet(slot, FrameSlotKind.Int);
         locals[slot.getIndex()] = value;
     }
 
     @Override
     public long getLong(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, long.class);
+        verifyGet(slot, FrameSlotKind.Long);
         return (long) locals[slot.getIndex()];
     }
 
     @Override
     public void setLong(FrameSlot slot, long value) throws FrameSlotTypeException {
-        verifySet(slot, long.class);
+        verifySet(slot, FrameSlotKind.Long);
         locals[slot.getIndex()] = value;
     }
 
     @Override
     public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, float.class);
+        verifyGet(slot, FrameSlotKind.Float);
         return (float) locals[slot.getIndex()];
     }
 
     @Override
     public void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException {
-        verifySet(slot, float.class);
+        verifySet(slot, FrameSlotKind.Float);
         locals[slot.getIndex()] = value;
     }
 
     @Override
     public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
-        verifyGet(slot, double.class);
+        verifyGet(slot, FrameSlotKind.Double);
         return (double) locals[slot.getIndex()];
     }
 
     @Override
     public void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException {
-        verifySet(slot, double.class);
+        verifySet(slot, FrameSlotKind.Double);
         locals[slot.getIndex()] = value;
     }
 
@@ -147,19 +147,19 @@
             assert index >= 0 && index < descriptor.getSize();
             return descriptor.getTypeConversion().getDefaultValue();
         }
-        Class tag = tags[index];
-        if (tag == null) {
+        byte tag = tags[index];
+        if (tag == FrameSlotKind.Illegal.ordinal()) {
             return descriptor.getTypeConversion().getDefaultValue();
         } else {
             return locals[index];
         }
     }
 
-    private void verifySet(FrameSlot slot, Class accessType) throws FrameSlotTypeException {
-        Class<?> slotType = slot.getType();
-        if (slotType != accessType) {
-            if (slotType == null) {
-                slot.setType(accessType);
+    private void verifySet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException {
+        FrameSlotKind slotKind = slot.getKind();
+        if (slotKind != accessKind) {
+            if (slotKind == FrameSlotKind.Illegal) {
+                slot.setKind(accessKind);
             } else {
                 throw new FrameSlotTypeException();
             }
@@ -168,14 +168,14 @@
         if (slotIndex >= tags.length) {
             resize();
         }
-        tags[slotIndex] = accessType;
+        tags[slotIndex] = (byte) accessKind.ordinal();
     }
 
-    private void verifyGet(FrameSlot slot, Class accessType) throws FrameSlotTypeException {
-        Class<?> slotType = slot.getType();
-        if (slotType != accessType) {
-            if (slotType == null && accessType == Object.class) {
-                slot.setType(Object.class);
+    private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException {
+        FrameSlotKind slotKind = slot.getKind();
+        if (slotKind != accessKind) {
+            if (slotKind == FrameSlotKind.Illegal && accessKind == FrameSlotKind.Object) {
+                slot.setKind(FrameSlotKind.Object);
                 this.setObject(slot, descriptor.getTypeConversion().getDefaultValue());
             } else {
                 throw new FrameSlotTypeException();
@@ -185,9 +185,9 @@
         if (slotIndex >= tags.length) {
             resize();
         }
-        if (tags[slotIndex] != accessType) {
+        if (tags[slotIndex] != accessKind.ordinal()) {
             descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot));
-            if (tags[slotIndex] != accessType) {
+            if (tags[slotIndex] != accessKind.ordinal()) {
                 throw new FrameSlotTypeException();
             }
         }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java	Fri Apr 26 18:38:56 2013 +0200
@@ -96,8 +96,7 @@
         }
     }
 
-    private static void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame,
-                    boolean includeImplicit) {
+    private void addInternalValueParameterNames(CodeTreeBuilder builder, TemplateMethod source, TemplateMethod specialization, String unexpectedValueName, boolean forceFrame, boolean includeImplicit) {
         if (forceFrame && specialization.getSpecification().findParameterSpec("frame") != null) {
             builder.string("frameValue");
         }
@@ -126,12 +125,12 @@
         }
     }
 
-    private static String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) {
+    private String valueName(ActualParameter sourceParameter, ActualParameter targetParameter) {
         if (sourceParameter != null) {
             if (!sourceParameter.getSpecification().isSignature()) {
                 return valueName(targetParameter);
             } else if (sourceParameter.getTypeSystemType() != null && targetParameter.getTypeSystemType() != null) {
-                if (sourceParameter.getTypeSystemType().needsCastTo(targetParameter.getTypeSystemType())) {
+                if (sourceParameter.getTypeSystemType().needsCastTo(getContext(), targetParameter.getTypeSystemType())) {
                     return castValueName(targetParameter);
                 }
             }
@@ -324,7 +323,7 @@
                     }
                     TypeData sourceType = sourceParameter.getTypeSystemType();
 
-                    if (sourceType.needsCastTo(targetType)) {
+                    if (sourceType.needsCastTo(getContext(), targetType)) {
                         valuesNeedsCast.add(targetParameter.getLocalName());
                     }
                 }
@@ -469,7 +468,7 @@
         TypeData targetType = target.getTypeSystemType();
         TypeData sourceType = source.getTypeSystemType();
 
-        if (!sourceType.needsCastTo(targetType)) {
+        if (!sourceType.needsCastTo(getContext(), targetType)) {
             return null;
         }
 
@@ -501,7 +500,7 @@
         TypeData sourceType = source.getTypeSystemType();
         TypeData targetType = target.getTypeSystemType();
 
-        if (!sourceType.needsCastTo(targetType)) {
+        if (!sourceType.needsCastTo(getContext(), targetType)) {
             return null;
         }
 
@@ -1639,7 +1638,7 @@
 
                 if (targetType == null || sourceType == null) {
                     builder.tree(returnBuilder.getRoot());
-                } else if (sourceType.needsCastTo(targetType)) {
+                } else if (sourceType.needsCastTo(getContext(), targetType)) {
                     builder.tree(createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.expectTypeMethodName(targetType), returnBuilder.getRoot()));
                 } else {
                     builder.tree(returnBuilder.getRoot());
@@ -1684,7 +1683,7 @@
                 CodeTree executionExpression = null;
                 if (cast || sourceParameter != null) {
                     TypeData sourceType = sourceParameter.getTypeSystemType();
-                    if (!sourceType.needsCastTo(targetType)) {
+                    if (!sourceType.needsCastTo(getContext(), targetType)) {
                         if (field.isShortCircuit() && sourceParameter != null) {
                             builder.tree(createShortCircuitValue(builder, specialization, field, targetParameter.getPreviousParameter(), unexpectedParameter));
                         }
@@ -1726,7 +1725,7 @@
             CodeTreeBuilder builder = new CodeTreeBuilder(parent);
             boolean unexpected = targetExecutable.hasUnexpectedValue(getContext());
             boolean cast = false;
-            if (targetExecutable.getType().needsCastTo(param.getTypeSystemType())) {
+            if (targetExecutable.getType().needsCastTo(getContext(), param.getTypeSystemType())) {
                 unexpected = true;
                 cast = true;
             }
@@ -1750,7 +1749,7 @@
             }
             builder.string(" = ");
             if (cast) {
-                builder.tree(createExpectType(specialization.getNode(), specialization.getReturnSignature(), body));
+                builder.tree(createExpectType(specialization.getNode(), param.getTypeSystemType(), body));
             } else {
                 builder.tree(body);
             }
@@ -1807,17 +1806,17 @@
                     if (index < signatureParameters.size()) {
                         ActualParameter specializationParam = signatureParameters.get(index);
 
+                        TypeData targetType = parameter.getTypeSystemType();
+                        TypeData sourceType = specializationParam.getTypeSystemType();
                         String localName = specializationParam.getLocalName();
                         if (unexpectedParameter != null && unexpectedParameter.getLocalName().equals(specializationParam.getLocalName())) {
                             localName = "ex.getResult()";
+                            sourceType = getModel().getNode().getTypeSystem().getGenericTypeData();
                         }
 
-                        TypeData sourceType = specializationParam.getTypeSystemType();
-                        TypeData targetType = parameter.getTypeSystemType();
-
                         CodeTree value = CodeTreeBuilder.singleString(localName);
 
-                        if (sourceType.needsCastTo(targetType)) {
+                        if (sourceType.needsCastTo(getContext(), targetType)) {
                             value = createCallTypeSystemMethod(getContext(), builder, getModel().getNode(), TypeSystemCodeGenerator.asTypeMethodName(targetType), value);
                         }
                         builder.tree(value);
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java	Fri Apr 26 18:38:56 2013 +0200
@@ -93,6 +93,10 @@
             if (type.hasUnexpectedValue(context)) {
                 return true;
             }
+            if (type.getReturnType().getTypeSystemType().needsCastTo(context, parameter.getTypeSystemType())) {
+                return true;
+            }
+
         }
         return false;
     }
--- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeData.java	Fri Apr 26 18:38:56 2013 +0200
@@ -110,13 +110,15 @@
         return Utils.typeEquals(boxedType, actualTypeData.boxedType);
     }
 
-    public boolean needsCastTo(TypeData targetType) {
+    public boolean needsCastTo(ProcessorContext context, TypeData targetType) {
         if (this.equals(targetType)) {
             return false;
         } else if (targetType.isGeneric()) {
             return false;
         } else if (targetType.isVoid()) {
             return false;
+        } else if (Utils.isAssignable(context, getPrimitiveType(), targetType.getPrimitiveType())) {
+            return false;
         }
         return true;
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java	Fri Apr 26 18:36:41 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java	Fri Apr 26 18:38:56 2013 +0200
@@ -59,7 +59,7 @@
     }
 
     public TypedNode createLocal(String name) {
-        return ReadLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, int.class));
+        return ReadLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, FrameSlotKind.Int));
     }
 
     public TypedNode createStringLiteral(String value) {
@@ -67,7 +67,7 @@
     }
 
     public StatementNode createAssignment(String name, TypedNode right) {
-        return WriteLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, int.class), right);
+        return WriteLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, FrameSlotKind.Int), right);
     }
 
     public StatementNode createPrint(List<TypedNode> expressions) {
@@ -123,7 +123,7 @@
     }
 
     public StatementNode createReturn(TypedNode value) {
-        FrameSlot slot = frameDescriptor.findOrAddFrameSlot("<retval>", int.class);
+        FrameSlot slot = frameDescriptor.findOrAddFrameSlot("<retval>", FrameSlotKind.Int);
         if (returnValue == null) {
             returnValue = ReadLocalNodeFactory.create(slot);
         }
--- a/mx/sanitycheck.py	Fri Apr 26 18:36:41 2013 +0200
+++ b/mx/sanitycheck.py	Fri Apr 26 18:38:56 2013 +0200
@@ -47,7 +47,8 @@
 }
 
 dacapoScalaSanityWarmup = {
-    'actors':     [0, 0, 2,  8, 10],
+# (tw) actors sometimes fails verification; hardly reproducible
+    'actors':     [0, 0, 0,  0,  0],
 # (lstadler) apparat was disabled due to a deadlock which I think is the benchmarks fault.
     'apparat':    [0, 0, 0,  0,  0],
     'factorie':   [0, 0, 2,  5,  5],
--- a/src/share/vm/graal/graalJavaAccess.hpp	Fri Apr 26 18:36:41 2013 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Fri Apr 26 18:38:56 2013 +0200
@@ -203,7 +203,7 @@
   end_class                                                                                                                                                    \
   start_class(Value)                                                                                                                                           \
     oop_field(Value, kind, "Lcom/oracle/graal/api/meta/Kind;")                                                                                                 \
-    static_oop_field(Value, ILLEGAL, "Lcom/oracle/graal/api/meta/Value;");                                                                                     \
+    static_oop_field(Value, ILLEGAL, "Lcom/oracle/graal/api/meta/AllocatableValue;");                                                                          \
   end_class                                                                                                                                                    \
   start_class(RegisterValue)                                                                                                                                   \
     oop_field(RegisterValue, reg, "Lcom/oracle/graal/api/code/Register;")                                                                                      \