# HG changeset patch # User Lukas Stadler # Date 1376911651 -7200 # Node ID a88f1ddbbad139b144ad0001b4a401da5e0021dd # Parent 307eec0f460f70dc4c7a31dd3f301ce7bd5b23a5# Parent f75491043d409cd651815acbd420d4821c9e0687 Merge diff -r 307eec0f460f -r a88f1ddbbad1 .hgignore --- 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/ diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java --- 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. diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- 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 shouldNotDeopt, Object receiver, Object... args) { Map 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)); } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- 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)); } } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java --- 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); diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- 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)); } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- 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; } } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- 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); diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- 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); } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java --- 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()); } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- 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); diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ConditionalElimination01.java --- /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}); + } + +} diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ConditionalElimination02.java --- /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}); + } + +} diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java --- 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(); } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopsData.java --- 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 innerFirst() { + ArrayList loops = new ArrayList<>(loops()); + Collections.sort(loops, new Comparator() { + + @Override + public int compare(LoopEx o1, LoopEx o2) { + return o2.lirLoop().depth - o1.lirLoop().depth; + } + }); + return loops; + } + public Collection countedLoops() { List counted = new LinkedList<>(); for (LoopEx loop : loops()) { diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java --- 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(); } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java --- 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; + } } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- 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 diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- 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()) { diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteMemoryCheckpointNode.java --- 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... - } -} diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- 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; + } } } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java --- 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); diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- 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; diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java --- 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); } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomTypeCheckNode.java --- 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; + } + } + } } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastMacroNode.java --- 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; } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java --- /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()); + } + } +} diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- 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); diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java --- 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 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 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)"; diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java --- 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 unsafeCast(Object value, Class 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 unsafeCast(Object value, Class clazz, Object customType) { + public static T unsafeCast(Object value, Class clazz, Object receiver, Object customType) { return (T) value; } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java --- 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++) { diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java --- 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); - } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinableCallSite.java --- 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); } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinedCallSite.java --- 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(); } diff -r 307eec0f460f -r a88f1ddbbad1 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- 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(); diff -r 307eec0f460f -r a88f1ddbbad1 mxtool/mx.py --- 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] ') for i in range(0, len(items)): diff -r 307eec0f460f -r a88f1ddbbad1 src/os_cpu/bsd_x86/vm/orderAccess_bsd_x86.inline.hpp --- 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 diff -r 307eec0f460f -r a88f1ddbbad1 src/share/vm/graal/graalCodeInstaller.cpp --- 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));