changeset 9347:f43d04388815

Merge.
author Christian Humer <christian.humer@gmail.com>
date Fri, 26 Apr 2013 22:44:05 +0200
parents 52fde777a605 (current diff) 52e6d0e8d6f7 (diff)
children 927e0792094b
files graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/reflect/Reflection_getCallerClass01.java
diffstat 43 files changed, 367 insertions(+), 372 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Fri Apr 26 22:44:05 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/phases/HighTier.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Fri Apr 26 22:44:05 2013 +0200
@@ -34,16 +34,10 @@
     public HighTier() {
         if (GraalOptions.FullUnroll) {
             addPhase(new LoopFullUnrollPhase());
-            if (GraalOptions.OptCanonicalizer) {
-                addPhase(new CanonicalizerPhase());
-            }
         }
 
         if (GraalOptions.OptTailDuplication) {
             addPhase(new TailDuplicationPhase());
-            if (GraalOptions.OptCanonicalizer) {
-                addPhase(new CanonicalizerPhase());
-            }
         }
 
         if (GraalOptions.PartialEscapeAnalysis) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Fri Apr 26 22:44:05 2013 +0200
@@ -47,7 +47,8 @@
     private int deletedNodeCount;
     private GraphEventLog eventLog;
 
-    InputChangedListener inputChanged;
+    NodeChangedListener inputChanged;
+    NodeChangedListener usagesDroppedZero;
     private final HashMap<CacheEntry, Node> cachedNodes = new HashMap<>();
 
     private static final class CacheEntry {
@@ -152,12 +153,12 @@
         return node;
     }
 
-    public interface InputChangedListener {
+    public interface NodeChangedListener {
 
-        void inputChanged(Node node);
+        void nodeChanged(Node node);
     }
 
-    public void trackInputChange(InputChangedListener inputChangedListener) {
+    public void trackInputChange(NodeChangedListener inputChangedListener) {
         this.inputChanged = inputChangedListener;
     }
 
@@ -165,6 +166,14 @@
         inputChanged = null;
     }
 
+    public void trackUsagesDroppedZero(NodeChangedListener usagesDroppedZeroListener) {
+        this.usagesDroppedZero = usagesDroppedZeroListener;
+    }
+
+    public void stopTrackingUsagesDroppedZero() {
+        usagesDroppedZero = null;
+    }
+
     /**
      * Adds a new node to the graph, if a <i>similar</i> node already exists in the graph, the
      * provided node will not be added to the graph but the <i>similar</i> node will be returned
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Fri Apr 26 22:44:05 2013 +0200
@@ -25,7 +25,7 @@
 import java.lang.annotation.*;
 import java.util.*;
 
-import com.oracle.graal.graph.Graph.InputChangedListener;
+import com.oracle.graal.graph.Graph.NodeChangedListener;
 import com.oracle.graal.graph.NodeClass.*;
 import com.oracle.graal.graph.iterators.*;
 
@@ -193,12 +193,17 @@
                 assert assertTrue(result, "not found in usages, old input: %s", oldInput);
             }
             if (newInput != null) {
-                InputChangedListener inputChanged = graph.inputChanged;
+                NodeChangedListener inputChanged = graph.inputChanged;
                 if (inputChanged != null) {
-                    inputChanged.inputChanged(this);
+                    inputChanged.nodeChanged(this);
                 }
                 assert newInput.usages != null : "not yet added? " + newInput;
                 newInput.usages.add(this);
+            } else if (oldInput != null && oldInput.usages().isEmpty()) {
+                NodeChangedListener nodeChangedListener = graph.usagesDroppedZero;
+                if (nodeChangedListener != null) {
+                    nodeChangedListener.nodeChanged(oldInput);
+                }
             }
         }
     }
@@ -253,9 +258,9 @@
             boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
             assert assertTrue(result, "not found in inputs, usage: %s", usage);
             if (other != null) {
-                InputChangedListener inputChanged = graph.inputChanged;
+                NodeChangedListener inputChanged = graph.inputChanged;
                 if (inputChanged != null) {
-                    inputChanged.inputChanged(usage);
+                    inputChanged.nodeChanged(usage);
                 }
                 other.usages.add(usage);
             }
@@ -299,6 +304,12 @@
 
         for (Node input : inputs()) {
             removeThisFromUsages(input);
+            if (input.usages().isEmpty()) {
+                NodeChangedListener nodeChangedListener = graph.usagesDroppedZero;
+                if (nodeChangedListener != null) {
+                    nodeChangedListener.nodeChanged(input);
+                }
+            }
         }
         getNodeClass().clearInputs(this);
     }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Apr 26 22:44:05 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.*;
@@ -234,6 +235,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));
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopySnippets.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java	Fri Apr 26 22:44:05 2013 +0200
@@ -608,11 +608,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 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Apr 26 22:44:05 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.jtt/src/com/oracle/graal/jtt/reflect/Reflection_getCallerClass01.java	Fri Apr 26 22:43:37 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.jtt.reflect;
-
-import com.oracle.graal.jtt.*;
-import org.junit.*;
-
-import sun.reflect.*;
-
-/*
- */
-public final class Reflection_getCallerClass01 extends JTTTest {
-
-    public static final class Caller1 {
-
-        private Caller1() {
-        }
-
-        static String caller1(int depth) {
-            return Reflection.getCallerClass(depth).getName();
-        }
-    }
-
-    public static final class Caller2 {
-
-        private Caller2() {
-        }
-
-        static String caller2(int depth) {
-            return Caller1.caller1(depth);
-        }
-    }
-
-    public static String test(int depth) {
-        return Caller2.caller2(depth);
-    }
-
-    @Test
-    public void run0() throws Throwable {
-        runTest("test", 0);
-    }
-
-    @Test
-    public void run1() throws Throwable {
-        runTest("test", 1);
-    }
-
-    @Test
-    public void run2() throws Throwable {
-        runTest("test", 2);
-    }
-
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Fri Apr 26 22:44:05 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.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Fri Apr 26 22:44:05 2013 +0200
@@ -22,14 +22,13 @@
  */
 package com.oracle.graal.phases.common;
 
-import java.util.*;
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Graph.InputChangedListener;
+import com.oracle.graal.graph.Graph.NodeChangedListener;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -49,6 +48,7 @@
     public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
 
     private final CustomCanonicalizer customCanonicalizer;
+    private final Iterable<Node> workingSet;
 
     public interface CustomCanonicalizer {
 
@@ -60,12 +60,17 @@
     }
 
     public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer) {
+        this(customCanonicalizer, null);
+    }
+
+    public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer, Iterable<Node> workingSet) {
         this.customCanonicalizer = customCanonicalizer;
+        this.workingSet = workingSet;
     }
 
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
-        new Instance(context.getRuntime(), context.getAssumptions(), null, customCanonicalizer).run(graph);
+        new Instance(context.getRuntime(), context.getAssumptions(), workingSet, customCanonicalizer).run(graph);
     }
 
     public static class Instance extends Phase {
@@ -78,7 +83,6 @@
 
         private NodeWorkList workList;
         private Tool tool;
-        private List<Node> snapshotTemp;
 
         public Instance(MetaAccessProvider runtime, Assumptions assumptions) {
             this(runtime, assumptions, null, 0, null);
@@ -110,7 +114,6 @@
             this.runtime = runtime;
             this.customCanonicalizer = customCanonicalizer;
             this.initWorkingSet = workingSet;
-            this.snapshotTemp = new ArrayList<>();
         }
 
         @Override
@@ -129,19 +132,22 @@
         }
 
         private void processWorkSet(StructuredGraph graph) {
-            graph.trackInputChange(new InputChangedListener() {
+            NodeChangedListener nodeChangedListener = new NodeChangedListener() {
 
                 @Override
-                public void inputChanged(Node node) {
+                public void nodeChanged(Node node) {
                     workList.addAgain(node);
                 }
-            });
+            };
+            graph.trackInputChange(nodeChangedListener);
+            graph.trackUsagesDroppedZero(nodeChangedListener);
 
             for (Node n : workList) {
                 processNode(n, graph);
             }
 
             graph.stopTrackingInputChange();
+            graph.stopTrackingUsagesDroppedZero();
         }
 
         private void processNode(Node node, StructuredGraph graph) {
@@ -153,17 +159,9 @@
                 }
                 int mark = graph.getMark();
                 if (!tryKillUnused(node)) {
-                    node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp);
                     if (!tryCanonicalize(node, graph)) {
                         tryInferStamp(node, graph);
-                    } else {
-                        for (Node in : snapshotTemp) {
-                            if (in.isAlive() && in.usages().isEmpty()) {
-                                GraphUtil.killWithUnusedFloatingInputs(in);
-                            }
-                        }
                     }
-                    snapshotTemp.clear();
                 }
 
                 for (Node newNode : graph.getNewNodes(mark)) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java	Fri Apr 26 22:44:05 2013 +0200
@@ -42,6 +42,7 @@
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class InliningUtil {
 
@@ -254,6 +255,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 +299,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 +383,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) {
@@ -446,7 +451,7 @@
             if (hasSingleMethod()) {
                 inlineSingleMethod(graph, callback, replacements, assumptions);
             } else {
-                inlineMultipleMethods(graph, callback, replacements, assumptions);
+                inlineMultipleMethods(graph, callback, replacements, assumptions, runtime);
             }
         }
 
@@ -458,7 +463,7 @@
             return notRecordedTypeProbability > 0;
         }
 
-        private void inlineMultipleMethods(StructuredGraph graph, InliningCallback callback, Replacements replacements, Assumptions assumptions) {
+        private void inlineMultipleMethods(StructuredGraph graph, InliningCallback callback, Replacements replacements, Assumptions assumptions, MetaAccessProvider runtime) {
             int numberOfMethods = concretes.size();
             FixedNode continuation = invoke.next();
 
@@ -560,7 +565,7 @@
                 if (opportunities > 0) {
                     metricInliningTailDuplication.increment();
                     Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities);
-                    TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes);
+                    TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, new HighTierContext(runtime, assumptions, replacements));
                 }
             }
         }
@@ -730,7 +735,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 +780,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.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Fri Apr 26 22:44:05 2013 +0200
@@ -24,7 +24,7 @@
 
 import java.util.*;
 
-import com.oracle.graal.graph.Graph.InputChangedListener;
+import com.oracle.graal.graph.Graph.NodeChangedListener;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
@@ -49,7 +49,7 @@
         }
     }
 
-    private static class Listener implements InputChangedListener {
+    private static class Listener implements NodeChangedListener {
 
         private final Set<Node> canonicalizationRoots;
 
@@ -58,7 +58,7 @@
         }
 
         @Override
-        public void inputChanged(Node node) {
+        public void nodeChanged(Node node) {
             canonicalizationRoots.add(node);
         }
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Fri Apr 26 22:44:05 2013 +0200
@@ -36,13 +36,14 @@
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.graph.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * This class is a phase that looks for opportunities for tail duplication. The static method
- * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List)} can also be used to drive tail
- * duplication from other places, e.g., inlining.
+ * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List, PhaseContext)} can also be used
+ * to drive tail duplication from other places, e.g., inlining.
  */
-public class TailDuplicationPhase extends Phase {
+public class TailDuplicationPhase extends BasePhase<PhaseContext> {
 
     /*
      * Various metrics on the circumstances in which tail duplication was/wasn't performed.
@@ -129,14 +130,14 @@
     };
 
     @Override
-    protected void run(StructuredGraph graph) {
+    protected void run(StructuredGraph graph, PhaseContext phaseContext) {
         NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(graph).apply();
 
         // A snapshot is taken here, so that new MergeNode instances aren't considered for tail
         // duplication.
         for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
             if (!(merge instanceof LoopBeginNode) && nodeProbabilities.get(merge) >= GraalOptions.TailDuplicationProbability) {
-                tailDuplicate(merge, DEFAULT_DECISION, null);
+                tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext);
             }
         }
     }
@@ -156,8 +157,9 @@
      *            size needs to match the merge's end count. Each entry can either be null or a
      *            {@link PiNode}, and is used to replace {@link PiNode#object()} with the
      *            {@link PiNode} in the duplicated branch that corresponds to the entry.
+     * @param phaseContext
      */
-    public static boolean tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List<PiNode> replacements) {
+    public static boolean tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List<PiNode> replacements, PhaseContext phaseContext) {
         assert !(merge instanceof LoopBeginNode);
         assert replacements == null || replacements.size() == merge.forwardEndCount();
         FixedNode fixed = merge;
@@ -171,14 +173,14 @@
                 metricDuplicationEnd.increment();
                 if (decision.doTransform(merge, fixedCount)) {
                     metricDuplicationEndPerformed.increment();
-                    new DuplicationOperation(merge, replacements).duplicate();
+                    new DuplicationOperation(merge, replacements).duplicate(phaseContext);
                     return true;
                 }
             } else if (merge.stateAfter() != null) {
                 metricDuplicationOther.increment();
                 if (decision.doTransform(merge, fixedCount)) {
                     metricDuplicationOtherPerformed.increment();
-                    new DuplicationOperation(merge, replacements).duplicate();
+                    new DuplicationOperation(merge, replacements).duplicate(phaseContext);
                     return true;
                 }
             }
@@ -220,10 +222,14 @@
          * <li>Determines the complete set of duplicated nodes.</li>
          * <li>Performs the actual duplication.</li>
          * </ul>
+         * 
+         * @param phaseContext
          */
-        private void duplicate() {
+        private void duplicate(PhaseContext phaseContext) {
             Debug.log("tail duplication at merge %s in %s", merge, graph.method());
 
+            int startMark = graph.getMark();
+
             ValueAnchorNode anchor = addValueAnchor();
 
             // determine the fixed nodes that should be duplicated (currently: all nodes up until
@@ -297,6 +303,7 @@
                     phi.setMerge(mergeAfter);
                 }
             }
+            new CanonicalizerPhase(null, graph.getNewNodes(startMark)).apply(graph, phaseContext);
             Debug.dump(graph, "After tail duplication at %s", merge);
         }
 
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Fri Apr 26 22:44:05 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/ReplacementsImpl.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Fri Apr 26 22:44:05 2013 +0200
@@ -282,6 +282,7 @@
             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/nodes/BranchProbabilityNode.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java	Fri Apr 26 22:44:05 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/MacroNode.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Fri Apr 26 22:44:05 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.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api.codegen.test/src/com/oracle/truffle/api/codegen/test/TypeSystemTest.java	Fri Apr 26 22:44:05 2013 +0200
@@ -115,7 +115,7 @@
         @Override
         public Object execute(VirtualFrame frame) {
             invocationCount++;
-            return ((TestArguments) frame.getArguments()).get(index);
+            return frame.getArguments(TestArguments.class).get(index);
         }
 
     }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ArgumentsTest.java	Fri Apr 26 22:44:05 2013 +0200
@@ -35,7 +35,7 @@
  * A guest language can pass its own custom arguments when invoking a Truffle method by creating a
  * subclass of {@link Arguments}. When invoking a call target with
  * {@link CallTarget#call(Arguments)}, the arguments can be passed. A Truffle node can access the
- * arguments passed into the Truffle method by using {@link VirtualFrame#getArguments()}.
+ * arguments passed into the Truffle method by using {@link VirtualFrame#getArguments}.
  * </p>
  * 
  * <p>
@@ -97,7 +97,7 @@
         }
 
         int execute(VirtualFrame frame) {
-            return ((TestArguments) frame.getArguments()).values[index];
+            return frame.getArguments(TestArguments.class).values[index];
         }
     }
 }
--- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Fri Apr 26 22:44:05 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/SourceSection.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java	Fri Apr 26 22:44:05 2013 +0200
@@ -117,4 +117,10 @@
     public final String getCode() {
         return getSource().getCode().substring(charIndex, charLength);
     }
+
+    @Override
+    public String toString() {
+        return String.format("%s:%d", source.getName(), startLine);
+    }
+
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java	Fri Apr 26 22:44:05 2013 +0200
@@ -36,9 +36,16 @@
     FrameDescriptor getFrameDescriptor();
 
     /**
+     * Retrieves the arguments object from this frame. The runtime assumes that the arguments object
+     * is never null. Additionally, the runtime may assume that the given parameter indicating the
+     * class of the arguments object is correct. The runtime is not required to actually check the
+     * type of the arguments object. The parameter must be a value that can be reduced to a compile
+     * time constant.
+     * 
+     * @param clazz the known type of the arguments object as a compile time constant
      * @return the arguments used when calling this method
      */
-    Arguments getArguments();
+    <T extends Arguments> T getArguments(Class<T> clazz);
 
     /**
      * Read access to a local variable of type {@link Object}.
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java	Fri Apr 26 22:44:05 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 22:44:05 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 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java	Fri Apr 26 22:44:05 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/frame/NativeFrame.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java	Fri Apr 26 22:44:05 2013 +0200
@@ -38,9 +38,10 @@
         this.arguments = arguments;
     }
 
+    @SuppressWarnings("unchecked")
     @Override
-    public Arguments getArguments() {
-        return arguments;
+    public <T extends Arguments> T getArguments(Class<T> clazz) {
+        return (T) arguments;
     }
 
     @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java	Fri Apr 26 22:44:05 2013 +0200
@@ -34,8 +34,8 @@
     }
 
     @Override
-    public Arguments getArguments() {
-        return wrapped.getArguments();
+    public <T extends Arguments> T getArguments(Class<T> clazz) {
+        return wrapped.getArguments(clazz);
     }
 
     @Override
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java	Fri Apr 26 22:44:05 2013 +0200
@@ -33,19 +33,20 @@
     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()];
     }
 
+    @SuppressWarnings("unchecked")
     @Override
-    public Arguments getArguments() {
-        return arguments;
+    public <T extends Arguments> T getArguments(Class<T> clazz) {
+        return (T) arguments;
     }
 
     @Override
@@ -65,73 +66,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 +148,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 +169,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 +186,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.sl/src/com/oracle/truffle/sl/NodeFactory.java	Fri Apr 26 22:43:37 2013 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java	Fri Apr 26 22:44:05 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 22:43:37 2013 +0200
+++ b/mx/sanitycheck.py	Fri Apr 26 22:44:05 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],