changeset 11358:a88f1ddbbad1

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Mon, 19 Aug 2013 13:27:31 +0200
parents 307eec0f460f (current diff) f75491043d40 (diff)
children 07625ef93345
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java
diffstat 38 files changed, 473 insertions(+), 169 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Aug 19 12:12:43 2013 +0200
+++ b/.hgignore	Mon Aug 19 13:27:31 2013 +0200
@@ -75,3 +75,4 @@
 coverage
 jacoco.exec
 workingsets.xml
+.buildbot/
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Mon Aug 19 13:27:31 2013 +0200
@@ -87,7 +87,8 @@
     TriState getExceptionSeen(int bci);
 
     /**
-     * Returns information if null was ever seen for the given BCI.
+     * Returns information if null was ever seen for the given BCI. This information is collected
+     * for the aastore, checkcast and instanceof bytecodes.
      * 
      * @return {@link TriState#TRUE} if null was seen for the instruction, {@link TriState#FALSE} if
      *         null was NOT seen, and {@link TriState#UNKNOWN} if this information was not recorded.
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Aug 19 13:27:31 2013 +0200
@@ -363,11 +363,13 @@
 
     protected Result executeActualCheckDeopt(Method method, Set<DeoptimizationReason> shouldNotDeopt, Object receiver, Object... args) {
         Map<DeoptimizationReason, Integer> deoptCounts = new EnumMap<>(DeoptimizationReason.class);
-        ProfilingInfo profile = runtime.lookupJavaMethod(method).getProfilingInfo();
+        ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method);
+        ProfilingInfo profile = javaMethod.getProfilingInfo();
         for (DeoptimizationReason reason : shouldNotDeopt) {
             deoptCounts.put(reason, profile.getDeoptimizationCount(reason));
         }
         Result actual = executeActual(method, receiver, args);
+        profile = javaMethod.getProfilingInfo(); // profile can change after execution
         for (DeoptimizationReason reason : shouldNotDeopt) {
             Assert.assertEquals((int) deoptCounts.get(reason), profile.getDeoptimizationCount(reason));
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Mon Aug 19 13:27:31 2013 +0200
@@ -667,11 +667,6 @@
             assert loadHub.kind() == wordKind;
             ValueNode object = loadHub.object();
             GuardingNode guard = loadHub.getGuard();
-            // A hub read must not float outside its block otherwise
-            // it may float above an explicit null check on its object.
-            if (guard == null) {
-                guard = AbstractBeginNode.prevBegin(tool.lastFixedNode());
-            }
             FloatingReadNode hub = createReadHub(graph, wordKind, object, guard);
             graph.replaceFloating(loadHub, hub);
         } else if (n instanceof LoadMethodNode) {
@@ -722,8 +717,8 @@
                                 value = allocations[commit.getVirtualObjects().indexOf(value)];
                             }
                             if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                                WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i)), BarrierType.NONE,
-                                                virtualInstance.field(i).getKind() == Kind.Object);
+                                WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i)),
+                                                virtualInstance.field(i).getKind() == Kind.Object ? BarrierType.IMPRECISE : BarrierType.NONE, virtualInstance.field(i).getKind() == Kind.Object);
 
                                 graph.addBeforeFixed(commit, graph.add(write));
                             }
@@ -740,8 +735,8 @@
                                 value = allocations[indexOf];
                             }
                             if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
-                                WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)), BarrierType.NONE,
-                                                value.kind() == Kind.Object);
+                                WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph)),
+                                                value.kind() == Kind.Object ? BarrierType.PRECISE : BarrierType.NONE, value.kind() == Kind.Object);
                                 graph.addBeforeFixed(commit, graph.add(write));
                             }
                         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java	Mon Aug 19 13:27:31 2013 +0200
@@ -37,7 +37,6 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.ConstantParameter;
 import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates;
 import com.oracle.graal.replacements.SnippetTemplate.Arguments;
 import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo;
@@ -49,17 +48,17 @@
 public class CheckCastDynamicSnippets implements Snippets {
 
     @Snippet
-    public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) {
-        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
+    public static Object checkcastDynamic(Word hub, Object object) {
+        if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
         } else {
-            BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+            BeginNode anchorNode = BeginNode.anchor();
             Word objectHub = loadHubIntrinsic(object, getWordKind(), anchorNode);
             if (!checkUnknownSubType(hub, objectHub)) {
                 DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException);
             }
         }
-        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        BeginNode anchorNode = BeginNode.anchor();
         return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
@@ -78,7 +77,6 @@
             Arguments args = new Arguments(dynamic);
             args.add("hub", checkcast.hub());
             args.add("object", object);
-            args.addConst("checkNull", !ObjectStamp.isObjectNonNull(object.stamp()));
 
             SnippetTemplate template = template(args);
             Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Aug 19 13:27:31 2013 +0200
@@ -495,7 +495,7 @@
 
     @SuppressWarnings("unused")
     @NodeIntrinsic(value = LoadHubNode.class, setStampFromReturnType = true)
-    static Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word, GuardingNode anchor) {
+    public static Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word, GuardingNode anchor) {
         return Word.unsigned(unsafeReadKlassPointer(object));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Aug 19 13:27:31 2013 +0200
@@ -79,8 +79,8 @@
      */
     @Snippet
     public static Object instanceofWithProfile(Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue,
-                    @ConstantParameter boolean checkNull, @ConstantParameter boolean nullSeen) {
-        if (probability(NOT_FREQUENT_PROBABILITY, checkNull && object == null)) {
+                    @ConstantParameter boolean nullSeen) {
+        if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
             if (!nullSeen) {
                 // See comment below for other deoptimization path; the
@@ -89,7 +89,7 @@
             }
             return falseValue;
         }
-        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        BeginNode anchorNode = BeginNode.anchor();
         Word objectHub = loadHubIntrinsic(object, getWordKind(), anchorNode);
         // if we get an exact match: succeed immediately
         ExplodeLoopNode.explodeLoop();
@@ -113,12 +113,12 @@
      * A test against a final type.
      */
     @Snippet
-    public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
-        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
+    public static Object instanceofExact(Object object, Word exactHub, Object trueValue, Object falseValue) {
+        if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
             return falseValue;
         }
-        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        BeginNode anchorNode = BeginNode.anchor();
         Word objectHub = loadHubIntrinsic(object, getWordKind(), anchorNode);
         if (probability(LIKELY_PROBABILITY, objectHub.notEqual(exactHub))) {
             exactMiss.inc();
@@ -132,12 +132,12 @@
      * A test against a primary type.
      */
     @Snippet
-    public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
-        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
+    public static Object instanceofPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue) {
+        if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
             return falseValue;
         }
-        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        BeginNode anchorNode = BeginNode.anchor();
         Word objectHub = loadHubIntrinsic(object, getWordKind(), anchorNode);
         if (probability(NOT_LIKELY_PROBABILITY, objectHub.readWord(superCheckOffset, LocationIdentity.FINAL_LOCATION).notEqual(hub))) {
             displayMiss.inc();
@@ -151,13 +151,12 @@
      * A test against a restricted secondary type type.
      */
     @Snippet
-    public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue,
-                    @ConstantParameter boolean checkNull) {
-        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
+    public static Object instanceofSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue) {
+        if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
             return falseValue;
         }
-        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        BeginNode anchorNode = BeginNode.anchor();
         Word objectHub = loadHubIntrinsic(object, getWordKind(), anchorNode);
         // if we get an exact match: succeed immediately
         ExplodeLoopNode.explodeLoop();
@@ -179,14 +178,13 @@
      * Type test used when the type being tested against is not known at compile time.
      */
     @Snippet
-    public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean checkNull) {
-        if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) {
+    public static Object instanceofDynamic(Class mirror, Object object, Object trueValue, Object falseValue) {
+        if (probability(NOT_FREQUENT_PROBABILITY, object == null)) {
             isNull.inc();
             return falseValue;
         }
-
+        BeginNode anchorNode = BeginNode.anchor();
         Word hub = loadWordFromObject(mirror, klassOffset());
-        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
         Word objectHub = loadHubIntrinsic(object, getWordKind(), anchorNode);
         if (!checkUnknownSubType(hub, objectHub)) {
             return falseValue;
@@ -242,7 +240,6 @@
                 }
                 args.add("trueValue", replacer.trueValue);
                 args.add("falseValue", replacer.falseValue);
-                args.addConst("checkNull", !ObjectStamp.isObjectNonNull(object.stamp()));
                 if (hintInfo.hintHitProbability >= hintHitProbabilityThresholdForDeoptimizingSnippet()) {
                     args.addConst("nullSeen", hintInfo.profile.getNullSeen() != TriState.FALSE);
                 }
@@ -258,7 +255,6 @@
                 args.add("object", object);
                 args.add("trueValue", replacer.trueValue);
                 args.add("falseValue", replacer.falseValue);
-                args.addConst("checkNull", !ObjectStamp.isObjectNonNull(object.stamp()));
                 return args;
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java	Mon Aug 19 13:27:31 2013 +0200
@@ -77,12 +77,13 @@
     public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced");
 
     @Snippet
-    public static void monitorenter(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) {
+    public static void monitorenter(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) {
         verifyOop(object);
 
-        if (checkNull && object == null) {
+        if (object == null) {
             DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
         }
+        BeginNode anchorNode = BeginNode.anchor();
 
         // Load the mark word - this includes a null-check on object
         final Word mark = loadWordFromObject(object, markOffset());
@@ -108,7 +109,7 @@
             } else {
                 // 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);
+                Word hub = loadHubIntrinsic(object, getWordKind(), anchorNode);
                 final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
                 final Word thread = thread();
                 final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace());
@@ -253,10 +254,10 @@
      * Calls straight out to the monitorenter stub.
      */
     @Snippet
-    public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean checkNull, @ConstantParameter boolean trace) {
+    public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) {
         verifyOop(object);
         incCounter();
-        if (checkNull && object == null) {
+        if (object == null) {
             DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException);
         }
         // BeginLockScope nodes do not read from object so a use of object
@@ -410,7 +411,6 @@
             }
             args.add("object", monitorenterNode.object());
             args.addConst("lockDepth", monitorenterNode.getLockDepth());
-            args.addConst("checkNull", !ObjectStamp.isObjectNonNull(monitorenterNode.object().stamp()));
             boolean tracingEnabledForMethod = stateAfter != null && (isTracingEnabledForMethod(stateAfter.method()) || isTracingEnabledForMethod(graph.method()));
             args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || tracingEnabledForMethod);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Mon Aug 19 13:27:31 2013 +0200
@@ -87,7 +87,7 @@
             new_stub.inc();
             result = NewInstanceStubCall.call(hub);
         }
-        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        BeginNode anchorNode = BeginNode.anchor();
         return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
@@ -121,7 +121,7 @@
             newarray_stub.inc();
             result = NewArrayStubCall.call(hub, length);
         }
-        BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic());
+        BeginNode anchorNode = BeginNode.anchor();
         return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic(), anchorNode);
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java	Mon Aug 19 13:27:31 2013 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.hotspot.nodes.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.Snippet.Fold;
 import com.oracle.graal.word.*;
@@ -217,12 +218,13 @@
 
             Pointer oop = Word.fromObject(object);
             if (object != null) {
+                BeginNode anchorNode = BeginNode.anchor();
                 // make sure object is 'reasonable'
                 if (!oop.and(unsigned(verifyOopMask())).equal(unsigned(verifyOopBits()))) {
                     fatal("oop not in heap: %p", oop.rawValue());
                 }
 
-                Word klass = loadHub(object);
+                Word klass = loadHubIntrinsic(object, getWordKind(), anchorNode);
                 if (klass.equal(Word.zero())) {
                     fatal("klass for oop %p is null", oop.rawValue());
                 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Aug 19 13:27:31 2013 +0200
@@ -696,6 +696,14 @@
             probability = 0.5;
         }
 
+        if (!optimisticOpts.removeNeverExecutedCode()) {
+            if (probability == 0) {
+                probability = 0.0000001;
+            } else if (probability == 1) {
+                probability = 0.999999;
+            }
+        }
+
         // the mirroring and negation operations get the condition into canonical form
         boolean mirror = cond.canonicalMirror();
         boolean negate = cond.canonicalNegate();
@@ -1137,9 +1145,12 @@
         if (graphBuilderConfig.eagerResolving()) {
             returnType = returnType.resolve(targetMethod.getDeclaringClass());
         }
-        if (invokeKind != InvokeKind.Static && invokeKind != InvokeKind.Special) {
-            JavaTypeProfile profile = profilingInfo.getTypeProfile(bci());
-            args[0] = TypeProfileProxyNode.create(args[0], profile);
+        if (invokeKind != InvokeKind.Static) {
+            emitExplicitExceptions(args[0], null);
+            if (invokeKind != InvokeKind.Special) {
+                JavaTypeProfile profile = profilingInfo.getTypeProfile(bci());
+                args[0] = TypeProfileProxyNode.create(args[0], profile);
+            }
         }
         MethodCallTargetNode callTarget = currentGraph.add(new MethodCallTargetNode(invokeKind, targetMethod, args, returnType));
         createInvokeNode(callTarget, resultType);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ConditionalElimination01.java	Mon Aug 19 13:27:31 2013 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.jtt.optimize;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.test.*;
+import com.oracle.graal.jtt.*;
+
+@SuppressWarnings("unused")
+public class ConditionalElimination01 extends JTTTest {
+
+    private static int x;
+    private static Object o = new Object();
+
+    private static class A {
+
+        public A(int y) {
+            this.y = y;
+        }
+
+        int y;
+    }
+
+    @Override
+    protected void before(Method method) {
+        super.before(method);
+        x = 0;
+    }
+
+    public int test(A a) {
+        if (o == null) {
+            return -1;
+        }
+        if (a == null) {
+            return -2;
+        }
+        if (o == null) {
+            return -3;
+        }
+        x = 3;
+        return a.y + x;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test", new A(5));
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        runTest("test", new Object[]{null});
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ConditionalElimination02.java	Mon Aug 19 13:27:31 2013 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.jtt.optimize;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.test.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.jtt.*;
+
+@SuppressWarnings("unused")
+public class ConditionalElimination02 extends JTTTest {
+
+    private static Object o = null;
+
+    private static class A {
+
+        public A(int y) {
+            this.y = y;
+        }
+
+        int y;
+    }
+
+    public int test(A a, boolean isNull, boolean isVeryNull) {
+        if (o == null) {
+            if (!isNull) {
+                if (o == null) {
+                    return a.y;
+                }
+            }
+            if (!isVeryNull) {
+                if (o == null) {
+                    return a.y;
+                }
+            }
+        }
+        return -1;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest(EnumSet.of(DeoptimizationReason.NullCheckException), "test", new A(5), false, false);
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        runTest(EnumSet.of(DeoptimizationReason.NullCheckException), "test", new Object[]{null, true, true});
+    }
+
+}
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Mon Aug 19 13:27:31 2013 +0200
@@ -126,6 +126,10 @@
         return iv.direction();
     }
 
+    public InductionVariable getCounter() {
+        return iv;
+    }
+
     public GuardingNode getOverFlowGuard() {
         return loop.loopBegin().getOverflowGuard();
     }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java	Mon Aug 19 13:27:31 2013 +0200
@@ -78,6 +78,18 @@
         return loops;
     }
 
+    public List<LoopEx> innerFirst() {
+        ArrayList<LoopEx> loops = new ArrayList<>(loops());
+        Collections.sort(loops, new Comparator<LoopEx>() {
+
+            @Override
+            public int compare(LoopEx o1, LoopEx o2) {
+                return o2.lirLoop().depth - o1.lirLoop().depth;
+            }
+        });
+        return loops;
+    }
+
     public Collection<LoopEx> countedLoops() {
         List<LoopEx> counted = new LinkedList<>();
         for (LoopEx loop : loops()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java	Mon Aug 19 13:27:31 2013 +0200
@@ -30,10 +30,6 @@
         super(StampFactory.dependency());
     }
 
-    protected BeginNode(Stamp stamp) {
-        super(stamp);
-    }
-
     @NodeIntrinsic
-    public static native BeginNode anchor(@ConstantNodeParameter Stamp stamp);
+    public static native BeginNode anchor();
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Mon Aug 19 13:27:31 2013 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
@@ -34,7 +35,7 @@
  * loop.
  */
 @NodeInfo(nameTemplate = "{p#type/s}Proxy")
-public class ProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable, ValueProxy {
+public class ProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable, ValueProxy, GuardingNode {
 
     @Input(notDataflow = true) private AbstractBeginNode proxyPoint;
     @Input private ValueNode value;
@@ -102,6 +103,10 @@
         }
     }
 
+    public static ProxyNode forGuard(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) {
+        return graph.unique(new ProxyNode(value, exit, PhiType.Guard, null));
+    }
+
     public static ProxyNode forValue(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) {
         return graph.unique(new ProxyNode(value, exit, PhiType.Value, null));
     }
@@ -114,4 +119,8 @@
     public ValueNode getOriginalValue() {
         return value;
     }
+
+    public ValueNode asNode() {
+        return this;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Aug 19 13:27:31 2013 +0200
@@ -59,7 +59,9 @@
 
     @Override
     public void lower(LoweringTool tool, LoweringType loweringType) {
-        tool.getRuntime().lower(this, tool);
+        if (loweringType == LoweringType.AFTER_GUARDS) {
+            tool.getRuntime().lower(this, tool);
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Aug 19 13:27:31 2013 +0200
@@ -32,21 +32,12 @@
  */
 public class UnsafeCastNode extends PiNode implements Canonicalizable, LIRLowerable {
 
-    private final Object customType;
-
     public UnsafeCastNode(ValueNode object, Stamp stamp) {
         super(object, stamp);
-        customType = null;
     }
 
     public UnsafeCastNode(ValueNode object, Stamp stamp, GuardingNode anchor) {
         super(object, stamp, anchor);
-        customType = null;
-    }
-
-    public UnsafeCastNode(ValueNode object, Stamp stamp, GuardingNode anchor, Object customType) {
-        super(object, stamp, anchor);
-        this.customType = customType;
     }
 
     public UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) {
@@ -57,10 +48,6 @@
         this(object, toType.getKind() == Kind.Object ? StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp())) : StampFactory.forKind(toType.getKind()));
     }
 
-    public Object getCustomType() {
-        return customType;
-    }
-
     @Override
     public boolean inferStamp() {
         if (stamp() == StampFactory.forNodeIntrinsic()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java	Mon Aug 19 12:12:43 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.extended;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public final class WriteMemoryCheckpointNode extends AbstractStateSplit implements StateSplit, LIRLowerable, MemoryCheckpoint.Single {
-
-    public WriteMemoryCheckpointNode() {
-        this(StampFactory.forVoid());
-    }
-
-    public WriteMemoryCheckpointNode(Stamp stamp) {
-        super(stamp);
-    }
-
-    @Override
-    public LocationIdentity getLocationIdentity() {
-        return LocationIdentity.ANY_LOCATION;
-    }
-
-    @Override
-    public void generate(LIRGeneratorTool generator) {
-        // nothing to do...
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Aug 19 13:27:31 2013 +0200
@@ -33,7 +33,8 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
@@ -489,15 +490,7 @@
                     boolean nonNull = state.isNonNull(object);
                     GuardingNode replacementAnchor = null;
                     if (nonNull) {
-                        // Search for valid instanceof anchor.
-                        for (InstanceOfNode instanceOfNode : object.usages().filter(InstanceOfNode.class)) {
-                            if (instanceOfNode.type() == checkCast.type() && state.trueConditions.containsKey(instanceOfNode)) {
-                                ValueNode v = state.trueConditions.get(instanceOfNode);
-                                if (v instanceof GuardingNode) {
-                                    replacementAnchor = (GuardingNode) v;
-                                }
-                            }
-                        }
+                        replacementAnchor = searchAnchor(GraphUtil.unproxify(object), type);
                     }
                     ValueAnchorNode anchor = null;
                     if (replacementAnchor == null) {
@@ -547,6 +540,10 @@
                 }
 
                 if (replacement != null) {
+                    if (replacementAnchor instanceof GuardNode) {
+                        ValueAnchorNode anchor = graph.add(new ValueAnchorNode(replacementAnchor));
+                        graph.addBeforeFixed(ifNode, anchor);
+                    }
                     for (Node n : survivingSuccessor.usages().snapshot()) {
                         if (n instanceof GuardNode || n instanceof ProxyNode) {
                             // Keep wired to the begin node.
@@ -555,7 +552,6 @@
                                 // Cannot simplify this IfNode as there is no anchor.
                                 return;
                             }
-
                             // Rewire to the replacement anchor.
                             n.replaceFirstInput(survivingSuccessor, replacementAnchor);
                         }
@@ -605,5 +601,34 @@
 
             }
         }
+
+        private GuardingNode searchAnchor(ValueNode value, ResolvedJavaType type) {
+            for (Node n : value.usages()) {
+                if (n instanceof InstanceOfNode) {
+                    InstanceOfNode instanceOfNode = (InstanceOfNode) n;
+                    if (instanceOfNode.type() == type && state.trueConditions.containsKey(instanceOfNode)) {
+                        ValueNode v = state.trueConditions.get(instanceOfNode);
+                        if (v instanceof GuardingNode) {
+                            return (GuardingNode) v;
+                        }
+                    }
+                }
+            }
+
+            for (Node n : value.usages()) {
+                if (n instanceof ValueProxy) {
+                    ValueProxy proxyNode = (ValueProxy) n;
+                    if (proxyNode.getOriginalValue() == value) {
+                        GuardingNode result = searchAnchor((ValueNode) n, type);
+                        if (result != null) {
+                            return result;
+                        }
+                    }
+
+                }
+            }
+
+            return null;
+        }
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Mon Aug 19 13:27:31 2013 +0200
@@ -86,12 +86,20 @@
                 survivingSuccessor = ifNode.trueSuccessor();
             }
             graph.removeSplitPropagate(ifNode, survivingSuccessor);
+            ProxyNode proxyGuard = null;
             for (Node n : survivingSuccessor.usages().snapshot()) {
                 if (n instanceof GuardNode || n instanceof ProxyNode) {
                     // Keep wired to the begin node.
                 } else {
                     // Rewire to the fixed guard.
-                    n.replaceFirstInput(survivingSuccessor, guard);
+                    if (survivingSuccessor instanceof LoopExitNode) {
+                        if (proxyGuard == null) {
+                            proxyGuard = ProxyNode.forGuard(guard, survivingSuccessor, graph);
+                        }
+                        n.replaceFirstInput(survivingSuccessor, proxyGuard);
+                    } else {
+                        n.replaceFirstInput(survivingSuccessor, guard);
+                    }
                 }
             }
             Debug.log("Converting %s on %-5s branch of %s to guard for remaining branch %s.", deopt, deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java	Mon Aug 19 13:27:31 2013 +0200
@@ -283,9 +283,6 @@
                             return inlineGraph;
                         }
                     });
-                    if (!methodCallTargetNode.isStatic() && ObjectStamp.isObjectAlwaysNull(methodCallTargetNode.receiver())) {
-                        return invoke.next();
-                    }
                     FixedNode fixedNode = (FixedNode) invoke.predecessor();
                     InliningUtil.inline(invoke, inlinedGraph, true);
                     return fixedNode;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java	Mon Aug 19 13:27:31 2013 +0200
@@ -22,10 +22,11 @@
  */
 package com.oracle.graal.truffle.nodes.arithmetic;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
-interface IntegerExactArithmeticNode extends Lowerable {
+interface IntegerExactArithmeticNode extends Lowerable, Node.IterableNodeType {
 
     IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt);
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomTypeCheckNode.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomTypeCheckNode.java	Mon Aug 19 13:27:31 2013 +0200
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
-public final class CustomTypeCheckNode extends LogicNode implements Lowerable, com.oracle.graal.graph.Node.IterableNodeType {
+public final class CustomTypeCheckNode extends LogicNode implements Lowerable, Virtualizable, com.oracle.graal.graph.Node.IterableNodeType {
 
     @Input private ValueNode condition;
     @Input private ValueNode object;
@@ -61,4 +61,15 @@
     public LogicNode canonical(CanonicalizerTool tool) {
         return this;
     }
+
+    public void virtualize(VirtualizerTool tool) {
+        if (getObject() != null) {
+            State objectState = tool.getObjectState(getObject());
+            if (objectState != null && objectState.getState() == EscapeState.Virtual) {
+                // The object is escape analyzed => cut the connection.
+                this.updateUsages(this.object, null);
+                this.object = null;
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastMacroNode.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastMacroNode.java	Mon Aug 19 13:27:31 2013 +0200
@@ -24,22 +24,21 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.truffle.nodes.asserts.*;
 import com.oracle.truffle.api.*;
 
 /**
  * Macro node for method {@link CompilerDirectives#unsafeCast(Object, Class)} and
- * {@link CompilerDirectives#unsafeCast(Object, Class, Object)}.
+ * {@link CompilerDirectives#unsafeCast(Object, Class, Object, Object)}.
  */
 public class TypeCastMacroNode extends NeverPartOfCompilationNode implements Canonicalizable {
 
-    private static final int ARGUMENT_COUNT = 3;
+    private static final int ARGUMENT_COUNT = 4;
     private static final int OBJECT_ARGUMENT_INDEX = 0;
     private static final int CLASS_ARGUMENT_INDEX = 1;
-    private static final int CUSTOM_TYPE_ARGUMENT_INDEX = 2;
+    private static final int RECEIVER_ARGUMENT_INDEX = 2;
+    private static final int CUSTOM_TYPE_ARGUMENT_INDEX = 3;
 
     public TypeCastMacroNode(Invoke invoke) {
         super(invoke, "The class of the unsafe cast could not be reduced to a compile time constant.");
@@ -53,13 +52,10 @@
         if (classArgument.isConstant() && customTypeArgument.isConstant()) {
             Class c = (Class) classArgument.asConstant().asObject();
             ResolvedJavaType lookupJavaType = tool.runtime().lookupJavaType(c);
-            Stamp s = StampFactory.declaredNonNull(lookupJavaType);
-            ValueAnchorNode valueAnchorNode = graph().add(new ValueAnchorNode());
             ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX);
+            ValueNode receiverArgument = arguments.get(RECEIVER_ARGUMENT_INDEX);
             Object customType = customTypeArgument.asConstant().asObject();
-            UnsafeCastNode unsafeCast = graph().unique(new UnsafeCastNode(objectArgument, s, valueAnchorNode, customType));
-            this.replaceAtUsages(unsafeCast);
-            return valueAnchorNode;
+            return graph().add(new TypeCastNode(objectArgument, lookupJavaType, receiverArgument, customType));
         }
         return this;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java	Mon Aug 19 13:27:31 2013 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, 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.truffle.nodes.typesystem;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public final class TypeCastNode extends FixedWithNextNode implements Lowerable, com.oracle.graal.graph.Node.IterableNodeType, ValueProxy, Virtualizable {
+
+    @Input private ValueNode receiver;
+    @Input private ValueNode object;
+    private final Object customType;
+    private final ResolvedJavaType castTarget;
+
+    public TypeCastNode(ValueNode object, ResolvedJavaType castTarget, ValueNode receiver, Object customType) {
+        super(StampFactory.declaredNonNull(castTarget));
+        this.receiver = receiver;
+        this.object = object;
+        this.customType = customType;
+        this.castTarget = castTarget;
+    }
+
+    public ValueNode getObject() {
+        return object;
+    }
+
+    public ValueNode getReceiver() {
+        return receiver;
+    }
+
+    public ResolvedJavaType getCastTarget() {
+        return castTarget;
+    }
+
+    public Object getCustomType() {
+        return customType;
+    }
+
+    public void lower(LoweringTool tool, LoweringType loweringType) {
+        if (loweringType == LoweringType.BEFORE_GUARDS) {
+            ValueAnchorNode valueAnchorNode = graph().add(new ValueAnchorNode());
+            UnsafeCastNode unsafeCast = graph().unique(new UnsafeCastNode(object, this.stamp(), (GuardingNode) valueAnchorNode));
+            this.replaceAtUsages(unsafeCast);
+            graph().replaceFixedWithFixed(this, valueAnchorNode);
+        }
+    }
+
+    public ValueNode getOriginalValue() {
+        return object;
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State state = tool.getObjectState(object);
+        if (state != null && state.getState() == EscapeState.Virtual) {
+            tool.replaceWithVirtual(state.getVirtualObject());
+        }
+    }
+}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java	Mon Aug 19 13:27:31 2013 +0200
@@ -65,7 +65,7 @@
     public static native void bailout(String reason);
 
     @MacroSubstitution(macro = TypeCastMacroNode.class, isStatic = true)
-    public static native Object unsafeCast(Object value, Class clazz, Object customType);
+    public static native Object unsafeCast(Object value, Class clazz, Object receiver, Object customType);
 
     @MacroSubstitution(macro = CustomTypeCheckMacroNode.class, isStatic = true)
     public static native boolean customTypeCheck(boolean condition, Object value, Object customType);
--- a/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java	Mon Aug 19 13:27:31 2013 +0200
@@ -31,6 +31,7 @@
 import com.oracle.truffle.api.dsl.test.BinaryNodeTest.BinaryNode;
 import com.oracle.truffle.api.dsl.test.PolymorphicTestFactory.Node1Factory;
 import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.nodes.NodeInfo.Kind;
 
@@ -44,6 +45,8 @@
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(boolean,int)", executeWith(node, false, 42));
         assertEquals(Kind.SPECIALIZED, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
+        assertEquals(node.getNode(), node.getNode().getRight().getParent());
     }
 
     @Test
@@ -52,6 +55,8 @@
         assertEquals("(int,boolean)", executeWith(node, 42, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
         assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
+        assertEquals(node.getNode(), node.getNode().getRight().getParent());
     }
 
     @Test
@@ -61,6 +66,8 @@
         assertEquals("(boolean,boolean)", executeWith(node, true, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
         assertEquals(Kind.POLYMORPHIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
+        assertEquals(node.getNode(), node.getNode().getRight().getParent());
     }
 
     @Test
@@ -71,6 +78,8 @@
         assertEquals("(boolean,boolean)", executeWith(node, true, false));
         assertEquals("(int,int)", executeWith(node, 42, 42));
         assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
+        assertEquals(node.getNode(), node.getNode().getRight().getParent());
     }
 
     @Test
@@ -78,21 +87,30 @@
         TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
         assertEquals("(generic,generic)", executeWith(node, "", ""));
         assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
+        assertEquals(node.getNode(), node.getNode().getRight().getParent());
     }
 
     @Test
-    public void testGenericPolymorphic() {
+    public void testGenericPolymorphic1() {
         TestRootNode<Node1> node = TestHelper.createRoot(Node1Factory.getInstance());
         assertEquals("(boolean,int)", executeWith(node, false, 42));
-        assertEquals("(int,boolean)", executeWith(node, 42, false));
+        assertEquals("(boolean,boolean)", executeWith(node, false, false));
         assertEquals("(generic,generic)", executeWith(node, "", ""));
         assertEquals(Kind.GENERIC, node.getNode().getClass().getAnnotation(NodeInfo.class).kind());
+        /* Assertions for bug GRAAL-425 */
+        assertEquals(node.getNode(), node.getNode().getLeft().getParent());
+        assertEquals(node.getNode(), node.getNode().getRight().getParent());
     }
 
     @SuppressWarnings("unused")
     @PolymorphicLimit(3)
     abstract static class Node1 extends BinaryNode {
 
+        public abstract ValueNode getLeft();
+
+        public abstract ValueNode getRight();
+
         @Specialization(order = 1)
         String add(int left, int right) {
             return "(int,int)";
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java	Mon Aug 19 13:27:31 2013 +0200
@@ -147,7 +147,7 @@
      */
     @Unsafe
     public static <T> T unsafeCast(Object value, Class<T> clazz) {
-        return unsafeCast(value, clazz, null);
+        return unsafeCast(value, clazz, null, null);
     }
 
     /**
@@ -168,12 +168,13 @@
      * 
      * @param value the value that is known to have the specified type
      * @param clazz the specified type of the value
+     * @param receiver the receiver on which the custom type is tested
      * @param customType the custom type that if present on a value makes this unsafe cast safe
      * @return the value
      */
     @SuppressWarnings("unchecked")
     @Unsafe
-    public static <T> T unsafeCast(Object value, Class<T> clazz, Object customType) {
+    public static <T> T unsafeCast(Object value, Class<T> clazz, Object receiver, Object customType) {
         return (T) value;
     }
 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java	Mon Aug 19 13:27:31 2013 +0200
@@ -101,10 +101,6 @@
         return Collections.unmodifiableSet(identifierToSlotMap.keySet());
     }
 
-    /**
-     * (db): this method is used for creating a clone of the {@link FrameDescriptor} object ready
-     * for parallel execution.
-     */
     public FrameDescriptor copy() {
         FrameDescriptor clonedFrameDescriptor = new FrameDescriptor(this.typeConversion);
         for (int i = 0; i < this.getSlots().size(); i++) {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java	Mon Aug 19 13:27:31 2013 +0200
@@ -27,8 +27,18 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 
+/**
+ * Factory for virtual frame creation.
+ */
 public interface FrameFactory {
 
+    /**
+     * Creates a new virtual frame from the given frame descriptor and arguments.
+     * 
+     * @param descriptor describes the frame to be created
+     * @param caller the packed caller frame or {@code null}
+     * @param args {@link Arguments} object to be stored in the frame
+     * @return a new virtual frame
+     */
     VirtualFrame create(FrameDescriptor descriptor, PackedFrame caller, Arguments args);
-
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinableCallSite.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinableCallSite.java	Mon Aug 19 13:27:31 2013 +0200
@@ -26,15 +26,44 @@
 
 import com.oracle.truffle.api.*;
 
+/**
+ * Denotes a call node that can inline the tree of its associated call target.
+ * 
+ * @see InlinedCallSite
+ */
 public interface InlinableCallSite {
 
+    /**
+     * Returns the number of calls since the last reset of the call count.
+     * 
+     * @return the current call count.
+     */
     int getCallCount();
 
+    /**
+     * Resets the call count to 0.
+     */
     void resetCallCount();
 
+    /**
+     * Returns the tree that would be inlined by a call to {@link #inline(FrameFactory)}.
+     * 
+     * @return the node tree to be inlined.
+     */
     Node getInlineTree();
 
+    /**
+     * Returns the call target associated with this call site.
+     * 
+     * @return the inlinable {@link CallTarget}.
+     */
     CallTarget getCallTarget();
 
+    /**
+     * Instructs the call node to inline the associated call target.
+     * 
+     * @param factory Frame factory for creating new virtual frames for inlined calls.
+     * @return {@code true} if call target was inlined; {@code false} otherwise.
+     */
     boolean inline(FrameFactory factory);
 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinedCallSite.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinedCallSite.java	Mon Aug 19 13:27:31 2013 +0200
@@ -26,7 +26,17 @@
 
 import com.oracle.truffle.api.*;
 
+/**
+ * Denotes a call node with an inlined call target. Allows for recursive call detection.
+ * 
+ * @see InlinableCallSite
+ */
 public interface InlinedCallSite {
 
+    /**
+     * Returns the call target that has been inlined at this call site.
+     * 
+     * @return the inlined call target.
+     */
     CallTarget getCallTarget();
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Mon Aug 19 12:12:43 2013 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java	Mon Aug 19 13:27:31 2013 +0200
@@ -1769,6 +1769,12 @@
             CodeTreeBuilder builder = parent.create();
             builder.declaration(getContext().getTruffleTypes().getNode(), "root", currentNode);
             builder.startIf().string(currentNode).string(".next0 != null").end().startBlock();
+            /*
+             * Communicates to the caller of executeAndSpecialize that it was rewritten to generic.
+             * Its important that this is used instead of the currentNode since the caller is this.
+             * CurrentNode may not be this anymore at this place.
+             */
+            builder.statement("this.next0 = null");
             builder.tree(createFindRoot(builder, node, false));
             builder.end();
             builder.end();
@@ -2502,9 +2508,10 @@
 
             builder.startIf().string("depth > ").string(String.valueOf(node.getPolymorphicDepth())).end();
             builder.startBlock();
-            String message = ("Polymorphic limit reached (" + node.getPolymorphicDepth() + ")");
+            String message = "Polymorphic limit reached (" + node.getPolymorphicDepth() + ")";
+            String castRoot = "(" + baseClassName(node) + ") root";
             builder.tree(createGenericInvoke(builder, node.getGenericPolymorphicSpecialization(), node.getGenericSpecialization(),
-                            createReplaceCall(builder, node.getGenericSpecialization(), "root", "this", message), null));
+                            createReplaceCall(builder, node.getGenericSpecialization(), "root", castRoot, message), null));
             builder.end();
 
             builder.startElseBlock();
@@ -2521,7 +2528,9 @@
 
             builder.declaration(node.getGenericSpecialization().getReturnType().getType(), "result", specializeCall.getRoot());
 
+            builder.startIf().string("this.next0 != null").end().startBlock();
             builder.startStatement().string("(").cast(nodePolymorphicClassName(node, node.getGenericPolymorphicSpecialization())).string("root).optimizeTypes()").end();
+            builder.end();
 
             if (Utils.isVoid(builder.findMethod().getReturnType())) {
                 builder.returnStatement();
--- a/mxtool/mx.py	Mon Aug 19 12:12:43 2013 +0200
+++ b/mxtool/mx.py	Mon Aug 19 13:27:31 2013 +0200
@@ -3326,9 +3326,9 @@
     Presents a command line interface for selecting one or more (if allowMultiple is true) items.
     
     """
-    if len(items) == 0:
-        return []
-    elif len(items) > 1:
+    if len(items) <= 1:
+        return items
+    else:
         if allowMultiple:
             log('[0] <all>')
         for i in range(0, len(items)):
--- a/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp	Mon Aug 19 12:12:43 2013 +0200
+++ b/src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp	Mon Aug 19 13:27:31 2013 +0200
@@ -190,7 +190,7 @@
 inline void     OrderAccess::release_store_fence(volatile julong*  p, julong  v) { release_store_fence((volatile jlong*)p,  (jlong)v);  }
 
 inline void     OrderAccess::release_store_fence(volatile jfloat*  p, jfloat  v) { *p = v; fence(); }
-inline void     OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jdouble_cast(v)); }
+inline void     OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { release_store_fence((volatile jlong*)p, jlong_cast(v)); }
 
 inline void     OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) {
 #ifdef AMD64
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Mon Aug 19 12:12:43 2013 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Mon Aug 19 13:27:31 2013 +0200
@@ -732,14 +732,6 @@
   NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset);
   jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method);
   
-  if (target->is_a(SystemDictionary::HotSpotInstalledCode_klass())) {
-    assert(inst->is_jump(), "jump expected");
-    CodeBlob* cb = (CodeBlob*) (address) HotSpotInstalledCode::codeBlob(target);
-    assert(cb != NULL, "npe");
-    CodeInstaller::pd_relocate_CodeBlob(cb, inst);
-    return;
-  }
-
   if (debug_info != NULL) {
     oop frame = DebugInfo::bytecodePosition(debug_info);
     _debug_recorder->add_safepoint(next_pc_offset, create_oop_map(_total_frame_size, _parameter_count, debug_info));