# HG changeset patch # User Josef Eisl # Date 1422958224 -3600 # Node ID 5e33637f5e5abda5bf23a766137250a306bd0d31 # Parent 336adcd0070b9cfba433c244a33fc1f569babb9b# Parent 684612ee6abbaf52e57fbcbf088c3add7df78446 Merge StackSlotAllocation cleanups. diff -r 684612ee6abb -r 5e33637f5e5a CHANGELOG.md --- a/CHANGELOG.md Sat Jan 31 15:51:54 2015 +0100 +++ b/CHANGELOG.md Tue Feb 03 11:10:24 2015 +0100 @@ -6,6 +6,7 @@ ## `tip` ### Graal * Add utilities ModifiersProvider#isConcrete, ResolvedJavaMethod#hasBytecodes, ResolvedJavaMethod#hasReceiver to Graal API. +* Add `GraalDirectives` API, containing methods to influence compiler behavior for unittests and microbenchmarks. * ... ### Truffle diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/BlackholeDirectiveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/BlackholeDirectiveTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.directives.test; + +import java.lang.annotation.*; + +import org.junit.*; + +import com.oracle.graal.api.directives.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; + +/** + * Tests for {@link GraalDirectives#blackhole}. + * + * There are two snippets for each kind: + * + * + */ +public class BlackholeDirectiveTest extends GraalCompilerTest { + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + private @interface BlackholeSnippet { + boolean expectParameterUsage(); + } + + @BlackholeSnippet(expectParameterUsage = false) + public static int booleanSnippet(int arg) { + boolean b = arg > 3; + if (b) { + return 1; + } else { + return 1; + } + } + + @BlackholeSnippet(expectParameterUsage = true) + public static int blackholeBooleanSnippet(int arg) { + boolean b = arg > 3; + GraalDirectives.blackhole(b); + if (b) { + return 1; + } else { + return 1; + } + } + + @Test + public void testBoolean() { + test("booleanSnippet", 5); + test("blackholeBooleanSnippet", 5); + } + + @BlackholeSnippet(expectParameterUsage = false) + public static int intSnippet(int arg) { + int x = 42 + arg; + return x - arg; + } + + @BlackholeSnippet(expectParameterUsage = true) + public static int blackholeIntSnippet(int arg) { + int x = 42 + arg; + GraalDirectives.blackhole(x); + return x - arg; + } + + @Test + public void testInt() { + test("intSnippet", 17); + test("blackholeIntSnippet", 17); + } + + private static class Dummy { + private int x = 42; + } + + @BlackholeSnippet(expectParameterUsage = false) + public static int objectSnippet(int arg) { + Dummy obj = new Dummy(); + int ret = obj.x; + obj.x = arg; + return ret; + } + + @BlackholeSnippet(expectParameterUsage = true) + public static int blackholeObjectSnippet(int arg) { + Dummy obj = new Dummy(); + int ret = obj.x; + obj.x = arg; + GraalDirectives.blackhole(obj); + return ret; + } + + @Test + public void testObject() { + test("objectSnippet", 37); + test("blackholeObjectSnippet", 37); + } + + @Override + protected boolean checkLowTierGraph(StructuredGraph graph) { + BlackholeSnippet snippet = graph.method().getAnnotation(BlackholeSnippet.class); + ParameterNode arg = graph.getParameter(0); + if (snippet.expectParameterUsage()) { + Assert.assertNotNull("couldn't find ParameterNode(0)", arg); + Assert.assertFalse("expected usages of " + arg, arg.hasNoUsages()); + } else { + Assert.assertTrue("expected no usages of ParameterNode", arg == null || arg.hasNoUsages()); + } + return true; + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/DeoptimizeDirectiveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/DeoptimizeDirectiveTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.directives.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.directives.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; + +public class DeoptimizeDirectiveTest extends GraalCompilerTest { + + public static boolean inCompiledCode() { + return GraalDirectives.inCompiledCode(); + } + + @Test + public void testInCompiledCode() { + ResolvedJavaMethod method = getResolvedJavaMethod("inCompiledCode"); + + Result interpreted = executeExpected(method, null); + assertEquals(new Result(false, null), interpreted); + + Result compiled = executeActual(method, null); + assertEquals(new Result(true, null), compiled); + } + + public static boolean deoptimizeSnippet() { + GraalDirectives.deoptimize(); + return GraalDirectives.inCompiledCode(); // should always return false + } + + public static boolean deoptimizeAndInvalidateSnippet() { + GraalDirectives.deoptimizeAndInvalidate(); + return GraalDirectives.inCompiledCode(); // should always return false + } + + @Test + public void testDeoptimize() { + test("deoptimizeSnippet"); + } + + private boolean testDeoptimizeCheckValid(ResolvedJavaMethod method) { + Result expected = executeExpected(method, null); + + InstalledCode code = getCode(method); + Result actual; + try { + actual = new Result(code.executeVarargs(), null); + } catch (Throwable e) { + actual = new Result(null, e); + } + + assertEquals(expected, actual); + return code.isValid(); + } + + @Test + public void testDeoptimizeAndInvalidate() { + ResolvedJavaMethod method = getResolvedJavaMethod("deoptimizeAndInvalidateSnippet"); + boolean valid = testDeoptimizeCheckValid(method); + Assert.assertFalse("code should be invalidated", valid); + } + + @Test + public void testDeoptimizeDontInvalidate() { + ResolvedJavaMethod method = getResolvedJavaMethod("deoptimizeSnippet"); + boolean valid = testDeoptimizeCheckValid(method); + Assert.assertTrue("code should still be valid", valid); + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/IterationDirectiveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/IterationDirectiveTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.directives.test; + +import org.junit.*; + +import com.oracle.graal.api.directives.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodes.*; + +public class IterationDirectiveTest extends GraalCompilerTest { + + public static int loopFrequencySnippet(int arg) { + int x = arg; + while (GraalDirectives.injectIterationCount(128, x > 1)) { + GraalDirectives.controlFlowAnchor(); // prevent loop peeling or unrolling + if (x % 2 == 0) { + x /= 2; + } else { + x = 3 * x + 1; + } + } + return x; + } + + @Test + public void testLoopFrequency() { + test("loopFrequencySnippet", 7); + } + + @Override + protected boolean checkLowTierGraph(StructuredGraph graph) { + NodeIterable loopBeginNodes = graph.getNodes(LoopBeginNode.class); + Assert.assertEquals("LoopBeginNode count", 1, loopBeginNodes.count()); + + LoopBeginNode loopBeginNode = loopBeginNodes.first(); + Assert.assertEquals("loop frequency of " + loopBeginNode, 128, loopBeginNode.loopFrequency(), 0); + + return true; + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/OpaqueDirectiveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/OpaqueDirectiveTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.directives.test; + +import java.lang.annotation.*; + +import org.junit.*; + +import com.oracle.graal.api.directives.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + +/** + * Tests for {@link GraalDirectives#opaque}. + * + * There are two snippets for each kind: + * + * + */ +public class OpaqueDirectiveTest extends GraalCompilerTest { + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + private @interface OpaqueSnippet { + Class expectedReturnNode(); + } + + @OpaqueSnippet(expectedReturnNode = ConstantNode.class) + public static boolean booleanSnippet() { + return 5 > 3; + } + + @OpaqueSnippet(expectedReturnNode = ConditionalNode.class) + public static boolean opaqueBooleanSnippet() { + return 5 > GraalDirectives.opaque(3); + } + + @Test + public void testBoolean() { + test("booleanSnippet"); + test("opaqueBooleanSnippet"); + } + + @OpaqueSnippet(expectedReturnNode = ConstantNode.class) + public static int intSnippet() { + return 5 + 3; + } + + @OpaqueSnippet(expectedReturnNode = AddNode.class) + public static int opaqueIntSnippet() { + return 5 + GraalDirectives.opaque(3); + } + + @Test + public void testInt() { + test("intSnippet"); + test("opaqueIntSnippet"); + } + + @OpaqueSnippet(expectedReturnNode = ConstantNode.class) + public static double doubleSnippet() { + return 5. + 3.; + } + + @OpaqueSnippet(expectedReturnNode = AddNode.class) + public static double opaqueDoubleSnippet() { + return 5. + GraalDirectives.opaque(3.); + } + + @Test + public void testDouble() { + test("doubleSnippet"); + test("opaqueDoubleSnippet"); + } + + private static class Dummy { + } + + @OpaqueSnippet(expectedReturnNode = ConstantNode.class) + public static boolean objectSnippet() { + Object obj = new Dummy(); + return obj == null; + } + + @OpaqueSnippet(expectedReturnNode = ConditionalNode.class) + public static boolean opaqueObjectSnippet() { + Object obj = new Dummy(); + return GraalDirectives.opaque(obj) == null; + } + + @Test + public void testObject() { + test("objectSnippet"); + test("opaqueObjectSnippet"); + } + + @Override + protected boolean checkLowTierGraph(StructuredGraph graph) { + OpaqueSnippet snippet = graph.method().getAnnotation(OpaqueSnippet.class); + for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) { + Assert.assertEquals(snippet.expectedReturnNode(), returnNode.result().getClass()); + } + return true; + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ProbabilityDirectiveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ProbabilityDirectiveTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.directives.test; + +import org.junit.*; + +import com.oracle.graal.api.directives.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodes.*; + +public class ProbabilityDirectiveTest extends GraalCompilerTest { + + public static int branchProbabilitySnippet(int arg) { + if (GraalDirectives.injectBranchProbability(0.125, arg > 0)) { + GraalDirectives.controlFlowAnchor(); // prevent removal of the if + return 1; + } else { + GraalDirectives.controlFlowAnchor(); // prevent removal of the if + return 2; + } + } + + @Test + public void testBranchProbability() { + test("branchProbabilitySnippet", 5); + } + + @Override + protected boolean checkLowTierGraph(StructuredGraph graph) { + NodeIterable ifNodes = graph.getNodes(IfNode.class); + Assert.assertEquals("IfNode count", 1, ifNodes.count()); + + IfNode ifNode = ifNodes.first(); + AbstractBeginNode trueSuccessor = ifNode.trueSuccessor(); + Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(trueSuccessor), 0); + + return true; + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.api.directives/src/com/oracle/graal/api/directives/GraalDirectives.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.directives/src/com/oracle/graal/api/directives/GraalDirectives.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.directives; + +/** + * Directives that influence the compilation of methods by Graal. They don't influence the semantics + * of the code, but they are useful for unit testing and benchmarking. + */ +public final class GraalDirectives { + + public static final double LIKELY_PROBABILITY = 0.75; + public static final double UNLIKELY_PROBABILITY = 1.0 - LIKELY_PROBABILITY; + + public static final double SLOWPATH_PROBABILITY = 0.0001; + public static final double FASTPATH_PROBABILITY = 1.0 - SLOWPATH_PROBABILITY; + + /** + * Directive for the compiler to fall back to the bytecode interpreter at this point. + */ + public static void deoptimize() { + } + + /** + * Directive for the compiler to fall back to the bytecode interpreter at this point, invalidate + * the compiled code and reprofile the method. + */ + public static void deoptimizeAndInvalidate() { + } + + /** + * Returns a boolean value indicating whether the method is executed in Graal-compiled code. + */ + public static boolean inCompiledCode() { + return false; + } + + /** + * A call to this method will never be duplicated by control flow optimizations in the compiler. + */ + public static void controlFlowAnchor() { + } + + /** + * Injects a probability for the given condition into the profiling information of a branch + * instruction. The probability must be a value between 0.0 and 1.0 (inclusive). + * + * Example usage (it specifies that the likelihood for a to be greater than b is 90%): + * + * + * if (injectBranchProbability(0.9, a > b)) { + * // ... + * } + * + * + * There are predefined constants for commonly used probabilities (see + * {@link #LIKELY_PROBABILITY} , {@link #UNLIKELY_PROBABILITY}, {@link #SLOWPATH_PROBABILITY}, + * {@link #FASTPATH_PROBABILITY} ). + * + * @param probability the probability value between 0.0 and 1.0 that should be injected + */ + public static boolean injectBranchProbability(double probability, boolean condition) { + assert probability >= 0.0 && probability <= 1.0; + return condition; + } + + /** + * Injects an average iteration count of a loop into the probability information of a loop exit + * condition. The iteration count specifies how often the condition is checked, i.e. in for and + * while loops it is one more than the body iteration count, and in do-while loops it is equal + * to the body iteration count. The iteration count must be >= 1.0. + * + * Example usage (it specifies that the expected iteration count of the loop condition is 500, + * so the iteration count of the loop body is 499): + * + * + * for (int i = 0; injectIterationCount(500, i < array.length); i++) { + * // ... + * } + * + * + * @param iterations the expected number of iterations that should be injected + */ + public static boolean injectIterationCount(double iterations, boolean condition) { + return injectBranchProbability(1. - 1. / iterations, condition); + } + + /** + * Consume a value, making sure the compiler doesn't optimize away the computation of this + * value, even if it is otherwise unused. + */ + @SuppressWarnings("unused") + public static void blackhole(boolean value) { + } + + /** + * Consume a value, making sure the compiler doesn't optimize away the computation of this + * value, even if it is otherwise unused. + */ + @SuppressWarnings("unused") + public static void blackhole(byte value) { + } + + /** + * Consume a value, making sure the compiler doesn't optimize away the computation of this + * value, even if it is otherwise unused. + */ + @SuppressWarnings("unused") + public static void blackhole(short value) { + } + + /** + * Consume a value, making sure the compiler doesn't optimize away the computation of this + * value, even if it is otherwise unused. + */ + @SuppressWarnings("unused") + public static void blackhole(char value) { + } + + /** + * Consume a value, making sure the compiler doesn't optimize away the computation of this + * value, even if it is otherwise unused. + */ + @SuppressWarnings("unused") + public static void blackhole(int value) { + } + + /** + * Consume a value, making sure the compiler doesn't optimize away the computation of this + * value, even if it is otherwise unused. + */ + @SuppressWarnings("unused") + public static void blackhole(long value) { + } + + /** + * Consume a value, making sure the compiler doesn't optimize away the computation of this + * value, even if it is otherwise unused. + */ + @SuppressWarnings("unused") + public static void blackhole(float value) { + } + + /** + * Consume a value, making sure the compiler doesn't optimize away the computation of this + * value, even if it is otherwise unused. + */ + @SuppressWarnings("unused") + public static void blackhole(double value) { + } + + /** + * Consume a value, making sure the compiler doesn't optimize away the computation of this + * value, even if it is otherwise unused. + */ + @SuppressWarnings("unused") + public static void blackhole(Object value) { + } + + /** + * Do nothing, but also make sure the compiler doesn't do any optimizations across this call. + * + * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 * + * opaque(3) will result in a real multiplication, because the compiler will not see that + * opaque(3) is a constant. + */ + public static boolean opaque(boolean value) { + return value; + } + + /** + * Do nothing, but also make sure the compiler doesn't do any optimizations across this call. + * + * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 * + * opaque(3) will result in a real multiplication, because the compiler will not see that + * opaque(3) is a constant. + */ + public static byte opaque(byte value) { + return value; + } + + /** + * Do nothing, but also make sure the compiler doesn't do any optimizations across this call. + * + * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 * + * opaque(3) will result in a real multiplication, because the compiler will not see that + * opaque(3) is a constant. + */ + public static short opaque(short value) { + return value; + } + + /** + * Do nothing, but also make sure the compiler doesn't do any optimizations across this call. + * + * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 * + * opaque(3) will result in a real multiplication, because the compiler will not see that + * opaque(3) is a constant. + */ + public static char opaque(char value) { + return value; + } + + /** + * Do nothing, but also make sure the compiler doesn't do any optimizations across this call. + * + * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 * + * opaque(3) will result in a real multiplication, because the compiler will not see that + * opaque(3) is a constant. + */ + public static int opaque(int value) { + return value; + } + + /** + * Do nothing, but also make sure the compiler doesn't do any optimizations across this call. + * + * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 * + * opaque(3) will result in a real multiplication, because the compiler will not see that + * opaque(3) is a constant. + */ + public static long opaque(long value) { + return value; + } + + /** + * Do nothing, but also make sure the compiler doesn't do any optimizations across this call. + * + * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 * + * opaque(3) will result in a real multiplication, because the compiler will not see that + * opaque(3) is a constant. + */ + public static float opaque(float value) { + return value; + } + + /** + * Do nothing, but also make sure the compiler doesn't do any optimizations across this call. + * + * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 * + * opaque(3) will result in a real multiplication, because the compiler will not see that + * opaque(3) is a constant. + */ + public static double opaque(double value) { + return value; + } + + /** + * Do nothing, but also make sure the compiler doesn't do any optimizations across this call. + * + * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 * + * opaque(3) will result in a real multiplication, because the compiler will not see that + * opaque(3) is a constant. + */ + public static T opaque(T value) { + return value; + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Services.java --- a/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Services.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Services.java Tue Feb 03 11:10:24 2015 +0100 @@ -38,7 +38,9 @@ protected List computeValue(Class type) { Service[] names = getServiceImpls(type); if (names == null || names.length == 0) { - throw new InternalError(format("No implementations for %s found (ensure %s extends %s)", type.getSimpleName(), type.getSimpleName(), Service.class)); + throw new InternalError( + format("No implementations for %s found (ensure %s extends %s and that in suite.py the \"annotationProcessors\" attribute for the project enclosing %s includes \"com.oracle.graal.service.processor\")", + type.getSimpleName(), type.getSimpleName(), Service.class, type.getSimpleName())); } return Arrays.asList(names); } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java --- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineCompiler.java Tue Feb 03 11:10:24 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; /** @@ -50,7 +51,7 @@ private final GraphBuilderConfiguration graphBuilderConfig; public CompilationResult generate(ResolvedJavaMethod method, int entryBCI, Backend backend, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, - CompilationResultBuilderFactory factory, OptimisticOptimizations optimisticOpts) { + CompilationResultBuilderFactory factory, OptimisticOptimizations optimisticOpts, Replacements replacements) { assert method.getCode() != null : "method must contain bytecodes: " + method; TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java Tue Feb 03 11:10:24 2015 +0100 @@ -317,6 +317,49 @@ return Arrays.asList(ops).stream().map(o -> o == null ? "null" : o.operator + "{" + getSimpleName(o.getClass(), false) + "}").collect(Collectors.joining(",")); } + private boolean opsEquals(ArithmeticOpTable that) { + // @formatter:off + return Objects.equals(neg, that.neg) && + Objects.equals(add, that.add) && + Objects.equals(sub, that.sub) && + Objects.equals(mul, that.mul) && + Objects.equals(div, that.div) && + Objects.equals(rem, that.rem) && + Objects.equals(not, that.not) && + Objects.equals(and, that.and) && + Objects.equals(or, that.or) && + Objects.equals(xor, that.xor) && + Objects.equals(shl, that.shl) && + Objects.equals(shr, that.shr) && + Objects.equals(ushr, that.ushr) && + Objects.equals(abs, that.abs) && + Objects.equals(sqrt, that.sqrt) && + Objects.equals(zeroExtend, that.zeroExtend) && + Objects.equals(signExtend, that.signExtend) && + Objects.equals(narrow, that.narrow); + // @formatter:on + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ArithmeticOpTable that = (ArithmeticOpTable) obj; + if (opsEquals(that)) { + if (Arrays.equals(this.floatConvert, that.floatConvert)) { + return true; + } + } + return false; + } + @Override public String toString() { return getClass().getSimpleName() + "[" + toString(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow) + ",floatConvert[" + @@ -337,19 +380,26 @@ } @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj != null && getClass() == obj.getClass()) { - return obj.toString().equals(toString()); - } - return false; + public int hashCode() { + return operator.hashCode(); } @Override - public int hashCode() { - return toString().hashCode(); + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Op that = (Op) obj; + if (operator.equals(that.operator)) { + return true; + } + return true; } } @@ -533,6 +583,36 @@ } @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + (associative ? 1231 : 1237); + result = prime * result + (commutative ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + BinaryOp that = (BinaryOp) obj; + if (associative != that.associative) { + return false; + } + if (commutative != that.commutative) { + return false; + } + return true; + } + + @Override public String toString() { if (associative) { if (commutative) { @@ -611,6 +691,30 @@ public FloatConvertOp unwrap() { return this; } + + @Override + public int hashCode() { + final int prime = 31; + return prime * super.hashCode() + op.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + FloatConvertOp that = (FloatConvertOp) obj; + if (op != that.op) { + return false; + } + return true; + } } public abstract static class IntegerConvertOp extends Op { diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticStamp.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticStamp.java Tue Feb 03 11:10:24 2015 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.common.type; import java.nio.*; +import java.util.*; import com.oracle.graal.api.meta.*; @@ -59,7 +60,7 @@ if (!(obj instanceof ArithmeticStamp)) { return false; } - assert this.ops.toString().equals(((ArithmeticStamp) obj).ops.toString()); + assert Objects.equals(ops, ((ArithmeticStamp) obj).ops); return true; } } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Tue Feb 03 11:10:24 2015 +0100 @@ -256,9 +256,6 @@ if (!(otherStamp instanceof IntegerStamp)) { return StampFactory.illegal(Kind.Illegal); } - if (equals(otherStamp)) { - return this; - } IntegerStamp other = (IntegerStamp) otherStamp; return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask); } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -325,7 +325,7 @@ canonicalizer.apply(graph, context); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); if (loopPeeling) { - new LoopTransformHighPhase().apply(graph); + new LoopPeelingPhase().apply(graph); } new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -67,7 +67,7 @@ StructuredGraph graph = new StructuredGraph(javaMethod); GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(); - new GraphBuilderPhase.Instance(getMetaAccess(), conf, OptimisticOptimizations.ALL).apply(graph); + new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), assumptions, conf, OptimisticOptimizations.ALL).apply(graph); HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); diff -r 684612ee6abb -r 5e33637f5e5a 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 Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.directives.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; @@ -524,7 +525,7 @@ try (Scope bds = Debug.scope("CompileBaseline", javaMethod, providers.getCodeCache())) { BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess()); OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL; - return baselineCompiler.generate(javaMethod, -1, getBackend(), new CompilationResult(), javaMethod, CompilationResultBuilderFactory.Default, optimisticOpts); + return baselineCompiler.generate(javaMethod, -1, getBackend(), new CompilationResult(), javaMethod, CompilationResultBuilderFactory.Default, optimisticOpts, getReplacements()); } catch (Throwable e) { throw Debug.handle(e); } @@ -720,7 +721,7 @@ StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner) : graph; lastCompiledGraph = graphToCompile; CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graphToCompile.method(), false); - Request request = new Request<>(graphToCompile, null, cc, installedCodeOwner, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), + Request request = new Request<>(graphToCompile, cc, installedCodeOwner, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graphToCompile), getSpeculationLog(), getSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); return GraalCompiler.compile(request); } @@ -855,7 +856,7 @@ * @return cond */ protected static boolean branchProbability(double p, boolean cond) { - return cond; + return GraalDirectives.injectBranchProbability(p, cond); } /** @@ -867,7 +868,7 @@ * @return cond */ protected static boolean iterationCount(double i, boolean cond) { - return cond; + return GraalDirectives.injectIterationCount(i, cond); } /** diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTestSubstitutions.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTestSubstitutions.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTestSubstitutions.java Tue Feb 03 11:10:24 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,22 +24,11 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; @ClassSubstitution(GraalCompilerTest.class) class GraalCompilerTestSubstitutions { @MethodSubstitution - public static boolean branchProbability(double p, boolean cond) { - return BranchProbabilityNode.probability(p, cond); - } - - @MethodSubstitution - public static boolean iterationCount(double i, boolean cond) { - return BranchProbabilityNode.probability(1. - 1. / i, cond); - } - - @MethodSubstitution public static void breakpoint() { BreakpointNode.breakpoint(); } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -60,7 +60,7 @@ final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); final StructuredGraph graph = parseEager(method); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - final CompilationResult cr = compileGraph(graph, null, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), + final CompilationResult cr = compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graph), null, getSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); @@ -83,7 +83,7 @@ assertTrue(graphLineSPs > 0); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); PhaseSuite graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()); - final CompilationResult cr = compileGraph(graph, null, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, + final CompilationResult cr = compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, getProfilingInfo(graph), getSpeculationLog(), getSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); int lineSPs = 0; for (Infopoint sp : cr.getInfopoints()) { diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -124,7 +124,7 @@ final StructuredGraph graph = parseEager(snippet); final StructuredGraph referenceGraph = parseEager(referenceSnippet); - new LoopTransformLowPhase().apply(graph); + new LoopUnswitchingPhase().apply(graph); // Framestates create comparison problems for (Node stateSplit : graph.getNodes().filterInterface(StateSplit.class)) { diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Tue Feb 03 11:10:24 2015 +0100 @@ -151,8 +151,8 @@ ResolvedJavaMethod method = getResolvedJavaMethod(snippet); graph = new StructuredGraph(method); try (Scope s = Debug.scope(getClass(), graph, method, getCodeCache())) { - new GraphBuilderPhase.Instance(getMetaAccess(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); Assumptions assumptions = new Assumptions(false); + new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), assumptions, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -339,8 +339,7 @@ @Test public void testPeeledLoop() { prepareGraph("testPeeledLoopSnippet", false); - new LoopTransformHighPhase().apply(graph); - new LoopTransformLowPhase().apply(graph); + new LoopPeelingPhase().apply(graph); new SchedulePhase().apply(graph); } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/GraalTutorial.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/GraalTutorial.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/GraalTutorial.java Tue Feb 03 11:10:24 2015 +0100 @@ -25,6 +25,8 @@ import org.junit.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.java.*; /** * Examples for the Graal tutorial. Run them using the unittest harness of the mx script. To look at @@ -38,15 +40,31 @@ public class GraalTutorial extends InvokeGraal { /* + * Example for the Graal API: access the Graal API metadata object for a method. + */ + + @Test + public void testPrintBytecodes() { + ResolvedJavaMethod method = findMethod(String.class, "hashCode"); + + byte[] bytecodes = method.getCode(); + Assert.assertNotNull(bytecodes); + + System.out.println(new BytecodeDisassembler().disassemble(method)); + } + + /* * A simple Graal compilation example: Compile the method String.hashCode() */ @Test public void testStringHashCode() throws InvalidInstalledCodeException { + int expectedResult = "Hello World".hashCode(); + InstalledCode installedCode = compileAndInstallMethod(findMethod(String.class, "hashCode")); int result = (int) installedCode.executeVarargs("Hello World"); - Assert.assertEquals(-862545276, result); + Assert.assertEquals(expectedResult, result); } /* @@ -70,7 +88,9 @@ /* * Collect profiling information by running the method in the interpreter. */ + for (int i = 0; i < 10000; i++) { + /* Execute several times so that enough profiling information gets collected. */ speculativeOptimization(false); } @@ -121,13 +141,17 @@ @Test public void testInstanceOfUsage() throws InvalidInstalledCodeException { - A a = new A(); + /* + * Collect profiling information by running the method in the interpreter. + */ - /* Allocate an (unsued) instance of B so that the class B gets loaded. */ + A a = new A(); + /* Allocate an (unused) instance of B so that the class B gets loaded. */ @SuppressWarnings("unused") B b = new B(); - + int expectedResult = instanceOfUsage(a); for (int i = 0; i < 10000; i++) { + /* Execute several times so that enough profiling information gets collected. */ instanceOfUsage(a); } @@ -136,7 +160,7 @@ InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "instanceOfUsage")); int result = (int) compiledMethod.executeVarargs(a); - Assert.assertEquals(42, result); + Assert.assertEquals(expectedResult, result); } /* @@ -149,9 +173,11 @@ @Test public void testIntrinsicUsage() throws InvalidInstalledCodeException { + double expectedResult = intrinsicUsage(42d); + InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "intrinsicUsage")); double result = (double) compiledMethod.executeVarargs(42d); - Assert.assertEquals(Math.sin(42), result, 0); + Assert.assertEquals(expectedResult, result, 0); } } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/InvokeGraal.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/InvokeGraal.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/InvokeGraal.java Tue Feb 03 11:10:24 2015 +0100 @@ -114,11 +114,10 @@ /* Advanced configuration objects that are not mandatory. */ Map cache = null; - Object stub = null; SpeculationLog speculationLog = null; /* Invoke the whole Graal compilation pipeline. */ - GraalCompiler.compileGraph(graph, stub, callingConvention, method, providers, backend, target, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites, + GraalCompiler.compileGraph(graph, callingConvention, method, providers, backend, target, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites, compilationResult, factory); /* diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Tue Feb 03 11:10:24 2015 +0100 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; @@ -33,6 +34,7 @@ import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; @@ -57,20 +59,23 @@ public class StaticAnalysis { /** Access to type, method, and fields using the Graal API. */ private final MetaAccessProvider metaAccess; + /** Access to platform dependent stamps. */ + private final StampProvider stampProvider; /** The results of the static analysis. */ private final Results results; /** Worklist for fixpoint iteration. */ private final Deque worklist; - public StaticAnalysis(MetaAccessProvider metaAccess) { + public StaticAnalysis(MetaAccessProvider metaAccess, StampProvider stampProvider) { this.metaAccess = metaAccess; + this.stampProvider = stampProvider; this.results = new Results(); this.worklist = new ArrayDeque<>(); } /** * Adds a root method to the static analysis. The method must be static and must not have any - * parameters, because the possible types of the parametes would not be known. + * parameters, because the possible types of the parameters would not be known. */ public void addMethod(ResolvedJavaMethod method) { if (!method.isStatic() || method.getSignature().getParameterCount(false) > 0) { @@ -217,7 +222,7 @@ * the code before static analysis, the classes would otherwise be not loaded * yet and the bytecode parser would only create a graph. */ - GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getEagerDefault().withOmitAllExceptionEdges(true); + GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getEagerDefault(); /* * For simplicity, we ignore all exception handling during the static analysis. * This is a constraint of this example code, a real static analysis needs to @@ -231,8 +236,9 @@ * wrong. */ OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE; + Assumptions assumptions = new Assumptions(false); - GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, graphBuilderConfig, optimisticOpts); + GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, assumptions, graphBuilderConfig, optimisticOpts); graphBuilder.apply(graph); } catch (Throwable ex) { Debug.handle(ex); @@ -305,7 +311,7 @@ * The active element for method invocations. For {@link InvokeKind#Virtual virtual} and * {@link InvokeKind#Interface interface} calls, the {@link TypeFlow#getTypes() types} of this * node are the receiver types. When a new receiver type is added, a new callee might be added. - * Adding a new callee means liking the type flow of the actual parameters with the formal + * Adding a new callee means linking the type flow of the actual parameters with the formal * parameters of the callee, and linking the return value of the callee with the return value * state of the invocation. * @@ -313,7 +319,6 @@ * {@link InvokeKind#Special special} calls) have only one callee, but use the same code for * simplicity. */ - class InvokeTypeFlow extends TypeFlow { private final MethodCallTargetNode callTarget; private final TypeFlow[] actualParameters; diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysisTests.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysisTests.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysisTests.java Tue Feb 03 11:10:24 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.compiler.test.tutorial.StaticAnalysis.MethodState; import com.oracle.graal.compiler.test.tutorial.StaticAnalysis.TypeFlow; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.runtime.*; @@ -58,12 +59,14 @@ Object f; } - private MetaAccessProvider metaAccess; + private final MetaAccessProvider metaAccess; + private final StampProvider stampProvider; public StaticAnalysisTests() { Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); Providers providers = backend.getProviders(); this.metaAccess = providers.getMetaAccess(); + this.stampProvider = providers.getStampProvider(); } static void test01Entry() { @@ -73,7 +76,7 @@ @Test public void test01() { - StaticAnalysis sa = new StaticAnalysis(metaAccess); + StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider); sa.addMethod(findMethod(StaticAnalysisTests.class, "test01Entry")); sa.finish(); @@ -94,7 +97,7 @@ @Test public void test02() { - StaticAnalysis sa = new StaticAnalysis(metaAccess); + StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider); sa.addMethod(findMethod(StaticAnalysisTests.class, "test02Entry")); sa.finish(); @@ -121,7 +124,7 @@ @Test public void test03() { - StaticAnalysis sa = new StaticAnalysis(metaAccess); + StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider); sa.addMethod(findMethod(StaticAnalysisTests.class, "test03Entry")); sa.finish(); @@ -151,7 +154,7 @@ @Test public void test04() { - StaticAnalysis sa = new StaticAnalysis(metaAccess); + StaticAnalysis sa = new StaticAnalysis(metaAccess, stampProvider); sa.addMethod(findMethod(StaticAnalysisTests.class, "test04Entry")); sa.finish(); diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Feb 03 11:10:24 2015 +0100 @@ -132,7 +132,6 @@ */ public static class Request { public final StructuredGraph graph; - public final Object stub; public final CallingConvention cc; public final ResolvedJavaMethod installedCodeOwner; public final Providers providers; @@ -152,7 +151,6 @@ * @param cc the calling convention for calls to the code compiled for {@code graph} * @param installedCodeOwner the method the compiled code will be associated with once * installed. This argument can be null. - * @param stub * @param providers * @param backend * @param target @@ -165,11 +163,10 @@ * @param compilationResult * @param factory */ - public Request(StructuredGraph graph, Object stub, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, TargetDescription target, + public Request(StructuredGraph graph, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, TargetDescription target, Map cache, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, SpeculationLog speculationLog, Suites suites, T compilationResult, CompilationResultBuilderFactory factory) { this.graph = graph; - this.stub = stub; this.cc = cc; this.installedCodeOwner = installedCodeOwner; this.providers = providers; @@ -204,11 +201,11 @@ * installed. This argument can be null. * @return the result of the compilation */ - public static T compileGraph(StructuredGraph graph, Object stub, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, + public static T compileGraph(StructuredGraph graph, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, TargetDescription target, Map cache, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, SpeculationLog speculationLog, Suites suites, T compilationResult, CompilationResultBuilderFactory factory) { - return compile(new Request<>(graph, stub, cc, installedCodeOwner, providers, backend, target, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites, - compilationResult, factory)); + return compile(new Request<>(graph, cc, installedCodeOwner, providers, backend, target, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites, compilationResult, + factory)); } /** @@ -221,7 +218,7 @@ try (Scope s0 = Debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache())) { Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); SchedulePhase schedule = emitFrontEnd(r.providers, r.target, r.graph, assumptions, r.cache, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.speculationLog, r.suites); - emitBackEnd(r.graph, r.stub, r.cc, r.installedCodeOwner, r.backend, r.target, r.compilationResult, r.factory, assumptions, schedule, null); + emitBackEnd(r.graph, null, r.cc, r.installedCodeOwner, r.backend, r.target, r.compilationResult, r.factory, assumptions, schedule, null); } catch (Throwable e) { throw Debug.handle(e); } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/GraphChangeMonitoringPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/GraphChangeMonitoringPhase.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/GraphChangeMonitoringPhase.java Tue Feb 03 11:10:24 2015 +0100 @@ -22,12 +22,11 @@ */ package com.oracle.graal.compiler.phases; -import static com.oracle.graal.graph.Graph.NodeEvent.*; - import java.util.stream.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.graph.Graph.NodeEvent; import com.oracle.graal.graph.Graph.NodeEventScope; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; @@ -60,9 +59,13 @@ @Override protected void run(StructuredGraph graph, C context) { - HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(INPUT_CHANGED); - try (NodeEventScope s = graph.trackNodeEvents(listener)) { - StructuredGraph graphCopy = graph.copy(); + /* + * Phase may add nodes but not end up using them so ignore additions. Nodes going dead and + * having their inputs change are the main interesting differences. + */ + HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(NodeEvent.NODE_ADDED); + StructuredGraph graphCopy = graph.copy(); + try (NodeEventScope s = graphCopy.trackNodeEvents(listener)) { try (Scope s2 = Debug.sandbox("WithoutMonitoring", null)) { super.run(graphCopy, context); } catch (Throwable t) { @@ -70,10 +73,10 @@ } } if (!listener.getNodes().isEmpty()) { - // rerun it on the real graph in a new Debug scope so Dump and Log can find it. - listener = new HashSetNodeEventListener().exclude(INPUT_CHANGED); + /* rerun it on the real graph in a new Debug scope so Dump and Log can find it. */ + listener = new HashSetNodeEventListener(); try (NodeEventScope s = graph.trackNodeEvents(listener)) { - try (Scope s2 = Debug.scope("GraphChangeMonitoring." + getName() + "-" + message)) { + try (Scope s2 = Debug.scope("WithGraphChangeMonitoring." + getName() + "-" + message)) { if (Debug.isDumpEnabled(BasePhase.PHASE_DUMP_LEVEL)) { Debug.dump(BasePhase.PHASE_DUMP_LEVEL, graph, "*** Before phase %s", getName()); } @@ -81,8 +84,8 @@ if (Debug.isDumpEnabled(BasePhase.PHASE_DUMP_LEVEL)) { Debug.dump(BasePhase.PHASE_DUMP_LEVEL, graph, "*** After phase %s", getName()); } + Debug.log("*** %s %s %s\n", message, graph, listener.getNodes().stream().filter(e -> !e.isAlive()).collect(Collectors.toSet())); } - Debug.log("*** %s %s %s\n", message, graph, listener.getNodes().stream().filter(e -> !e.isAlive()).collect(Collectors.toSet())); } } else { // Go ahead and run it normally even though it should have no effect diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Tue Feb 03 11:10:24 2015 +0100 @@ -85,8 +85,12 @@ } if (OptLoopTransform.getValue()) { - appendPhase(new LoopTransformHighPhase()); - appendPhase(new LoopTransformLowPhase()); + if (LoopPeeling.getValue()) { + appendPhase(new LoopPeelingPhase()); + } + if (LoopUnswitch.getValue()) { + appendPhase(new LoopUnswitchingPhase()); + } } appendPhase(new RemoveValueProxyPhase()); diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Tue Feb 03 11:10:24 2015 +0100 @@ -89,6 +89,10 @@ appendPhase(new FrameStateAssignmentPhase()); + if (ReassociateInvariants.getValue()) { + appendPhase(new ReassociateInvariantPhase()); + } + if (OptDeoptimizationGrouping.getValue()) { appendPhase(new DeoptimizationGroupingPhase()); } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Tue Feb 03 11:10:24 2015 +0100 @@ -331,7 +331,13 @@ } else { subIndex++; } - while (index < edges.getCount()) { + if (index < edges.getCount()) { + forwardNodeList(); + } + } + + private void forwardNodeList() { + do { if (subIndex == 0) { list = edges.getNodeList(node, index); } @@ -346,7 +352,7 @@ } subIndex = 0; index++; - } + } while (index < edges.getCount()); } private Node nextElement() { diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Tue Feb 03 11:10:24 2015 +0100 @@ -166,7 +166,7 @@ isLeafNode = inputs.getCount() + successors.getCount() == 0; canGVN = Node.ValueNumberable.class.isAssignableFrom(clazz); - startGVNNumber = clazz.getName().hashCode(); + startGVNNumber = clazz.hashCode(); NodeInfo info = getAnnotationTimed(clazz, NodeInfo.class); assert info != null : "Missing NodeInfo annotation on " + clazz; diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Tue Feb 03 11:10:24 2015 +0100 @@ -98,6 +98,14 @@ values[getNodeId(node)] = value; } + /** + * @param i + * @return Return the key for the entry at index {@code i} + */ + protected Node getKey(int i) { + return graph.getNode(i); + } + public int size() { return values.length; } @@ -135,7 +143,7 @@ @Override public Entry next() { final int pos = i; - Node key = NodeMap.this.graph.getNode(pos); + Node key = NodeMap.this.getKey(pos); T value = (T) NodeMap.this.values[pos]; i++; forward(); @@ -158,7 +166,7 @@ } private void forward() { - while (i < NodeMap.this.values.length && (NodeMap.this.graph.getNode(i) == null || NodeMap.this.values[i] == null)) { + while (i < NodeMap.this.values.length && (NodeMap.this.getKey(i) == null || NodeMap.this.values[i] == null)) { i++; } } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java Tue Feb 03 11:10:24 2015 +0100 @@ -56,10 +56,21 @@ public Set keySet() { HashSet entries = new HashSet<>(); - for (Map.Entry entry : entries()) { - entries.add(entry.getKey()); + for (int i = 0; i < values.length; ++i) { + Object v = values[i]; + if (v != null) { + Node key = getKey(i); + if (key != null) { + entries.add(key); + } + } } - return entries; + /* + * The normal contract for entrySet is that modifications of the set are reflected in the + * underlying data structure. For simplicity don't allow that but complain if someone tries + * to use it that way. + */ + return Collections.unmodifiableSet(entries); } public Collection values() { @@ -78,6 +89,11 @@ for (Map.Entry entry : entries()) { entries.add(entry); } - return entries; + /* + * The normal contract for entrySet is that modifications of the set are reflected in the + * underlying data structure. For simplicity don't allow that but complain if someone tries + * to use it that way. + */ + return Collections.unmodifiableSet(entries); } } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Tue Feb 03 11:10:24 2015 +0100 @@ -210,7 +210,7 @@ CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); // create suites everytime, as we modify options for the compiler final Suites suitesLocal = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().createSuites(); - final CompilationResult compResult = compileGraph(graph, null, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), + final CompilationResult compResult = compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graph), getSpeculationLog(), suitesLocal, new CompilationResult(), CompilationResultBuilderFactory.Default); addMethod(method, compResult); } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Tue Feb 03 11:10:24 2015 +0100 @@ -197,7 +197,7 @@ HotSpotProviders providers = backend.getProviders(); BaselineCompiler baselineCompiler = new BaselineCompiler(GraphBuilderConfiguration.getDefault(), providers.getMetaAccess()); OptimisticOptimizations optimisticOpts = OptimisticOptimizations.ALL; - result = baselineCompiler.generate(method, -1, backend, new CompilationResult(), method, CompilationResultBuilderFactory.Default, optimisticOpts); + result = baselineCompiler.generate(method, -1, backend, new CompilationResult(), method, CompilationResultBuilderFactory.Default, optimisticOpts, providers.getReplacements()); } else { Map graphCache = null; if (GraalOptions.CacheGraphs.getValue()) { @@ -230,7 +230,7 @@ // all code after the OSR loop is never executed. optimisticOpts.remove(Optimization.RemoveNeverExecutedCode); } - result = compileGraph(graph, null, cc, method, providers, backend, backend.getTarget(), graphCache, getGraphBuilderSuite(providers), optimisticOpts, profilingInfo, + result = compileGraph(graph, cc, method, providers, backend, backend.getTarget(), graphCache, getGraphBuilderSuite(providers), optimisticOpts, profilingInfo, method.getSpeculationLog(), suites, new CompilationResult(), CompilationResultBuilderFactory.Default); } result.setId(getId()); diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Feb 03 11:10:24 2015 +0100 @@ -91,6 +91,7 @@ * Do deferred initialization. */ public void completeInitialization() { + TTY.initialize(Options.LogFile.getStream(compilerToVm)); // Proxies for the VM/Compiler interfaces cannot be initialized // in the constructor as proxy creation causes static @@ -109,8 +110,6 @@ this.compilerToVm = toVM; - TTY.initialize(Options.LogFile.getStream(compilerToVm)); - if (Log.getValue() == null && Meter.getValue() == null && Time.getValue() == null && Dump.getValue() == null && Verify.getValue() == null) { if (MethodFilter.getValue() != null) { TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time, Dump and Verify options are all null"); diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Tue Feb 03 11:10:24 2015 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.java.*; import com.oracle.graal.nodes.spi.*; /** @@ -65,6 +66,15 @@ HotSpotHostForeignCallsProvider foreignCalls = (HotSpotHostForeignCallsProvider) providers.getForeignCalls(); final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); + try (InitTimer st = timer("graphBuilderPlugins.initialize")) { + GraphBuilderPhase phase = (GraphBuilderPhase) providers.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous(); + GraphBuilderPlugins plugins = phase.getGraphBuilderPlugins(); + Iterable sl = Services.load(GraphBuilderPluginsProvider.class); + for (GraphBuilderPluginsProvider p : sl) { + p.registerPlugins(providers.getMetaAccess(), plugins); + } + } + try (InitTimer st = timer("foreignCalls.initialize")) { foreignCalls.initialize(providers, config); } @@ -92,6 +102,5 @@ throw Debug.handle(e); } } - } } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/CountingProxy.java Tue Feb 03 11:10:24 2015 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.logging; -import java.io.*; import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; @@ -97,13 +96,12 @@ protected void print() { long sum = 0; - PrintStream out = System.out; for (Map.Entry entry : calls.entrySet()) { Method method = entry.getKey(); long count = entry.getValue().get(); sum += count; - out.println(delegate.getClass().getSimpleName() + "." + method.getName() + ": " + count); + TTY.println(delegate.getClass().getSimpleName() + "." + method.getName() + ": " + count); } - out.println(delegate.getClass().getSimpleName() + " calls: " + sum); + TTY.println(delegate.getClass().getSimpleName() + " calls: " + sum); } } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Tue Feb 03 11:10:24 2015 +0100 @@ -30,7 +30,7 @@ import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; -import com.oracle.graal.java.GraphBuilderConfiguration.*; +import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Tue Feb 03 11:10:24 2015 +0100 @@ -162,7 +162,7 @@ Suites suites = providers.getSuites().createSuites(); PhaseSuite phaseSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy(); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, g.method(), false); - CompilationResult compResult = GraalCompiler.compileGraph(g, null, cc, g.method(), providers, backend, backend.getTarget(), null, phaseSuite, OptimisticOptimizations.ALL, + CompilationResult compResult = GraalCompiler.compileGraph(g, cc, g.method(), providers, backend, backend.getTarget(), null, phaseSuite, OptimisticOptimizations.ALL, DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, new CompilationResult(), CompilationResultBuilderFactory.Default); InstalledCode installedCode; try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) { diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Tue Feb 03 11:10:24 2015 +0100 @@ -105,7 +105,7 @@ if (superKlass.equal(0)) { return null; } else { - return piCastExactNonNull(superKlass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION), Class.class); + return readJavaMirror(superKlass); } } } @@ -113,6 +113,10 @@ return null; } + public static Class readJavaMirror(Word klass) { + return piCastExactNonNull(klass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION), Class.class); + } + @MacroSubstitution(macro = ClassGetComponentTypeNode.class, isStatic = false) @MethodSubstitution(isStatic = false) public static Class getComponentType(final Class thisObj) { diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompilerToVMImplSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CompilerToVMImplSubstitutions.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.word.*; + +/** + * Substitutions for {@link CompilerToVMImpl} methods. + */ +@ClassSubstitution(com.oracle.graal.hotspot.bridge.CompilerToVMImpl.class) +public class CompilerToVMImplSubstitutions { + + @MethodSubstitution(isStatic = false) + public static Class getJavaMirror(@SuppressWarnings("unused") CompilerToVMImpl impl, long metaspaceklass) { + return ClassSubstitutions.readJavaMirror(Word.unsigned(metaspaceklass)); + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Provider of HotSpot specific {@link GraphBuilderPlugin}s. + */ +@ServiceProvider(GraphBuilderPluginsProvider.class) +public class HotSpotGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { + public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + plugins.register(metaAccess, ObjectPlugin.class); + } + + /** + * HotSpot specific plugins for {@link Object}. + */ + enum ObjectPlugin implements GraphBuilderPlugin { + getClass() { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + assert args.length == 1; + ValueNode rcvr = args[0]; + GuardingPiNode pi = builder.append(new GuardingPiNode(rcvr)); + StampProvider stampProvider = builder.getStampProvider(); + LoadHubNode hub = builder.append(new LoadHubNode(stampProvider, pi)); + HubGetClassNode mirror = builder.append(new HubGetClassNode(builder.getMetaAccess(), hub)); + builder.push(Kind.Object, mirror); + return true; + } + }; + + public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) { + return GraphBuilderPlugin.resolveTarget(metaAccess, Object.class, name()); + } + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Tue Feb 03 11:10:24 2015 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; @@ -65,6 +66,7 @@ replacements.registerSubstitutions(NodeClass.class, HotSpotNodeClassSubstitutions.class); replacements.registerSubstitutions(Node.class, HotSpotNodeSubstitutions.class); replacements.registerSubstitutions(CompositeValueClass.class, CompositeValueClassSubstitutions.class); + replacements.registerSubstitutions(CompilerToVMImpl.class, CompilerToVMImplSubstitutions.class); replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.AESCrypt"), AESCryptSubstitutions.class); replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.CipherBlockChaining"), CipherBlockChainingSubstitutions.class); } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Tue Feb 03 11:10:24 2015 +0100 @@ -1153,5 +1153,4 @@ } Debug.log("%s", sb); } - } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPluginsProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPluginsProvider.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; + +/** + * Provider of non-runtime specific {@link GraphBuilderPlugin}s. + */ +@ServiceProvider(GraphBuilderPluginsProvider.class) +public class DefaultGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { + public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + plugins.register(metaAccess, ObjectPlugin.class); + plugins.register(metaAccess, BoxingPlugin.class); + } + + /** + * Plugins for {@link Object}. + */ + enum ObjectPlugin implements GraphBuilderPlugin { + init() { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + ValueNode object = args[0]; + if (RegisterFinalizerNode.mayHaveFinalizer(object, builder.getAssumptions())) { + builder.append(new RegisterFinalizerNode(object)); + } + return true; + } + + public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) { + return GraphBuilderPlugin.resolveTarget(metaAccess, Object.class, ""); + } + }; + + @Override + public String toString() { + return Object.class.getName() + "." + name() + "()"; + } + } + + /** + * Plugins for the standard primitive box classes (e.g., {@link Integer} and friends). + */ + enum BoxingPlugin implements GraphBuilderPlugin { + valueOf$Boolean(Kind.Boolean), + booleanValue$Boolean(Kind.Boolean), + valueOf$Byte(Kind.Byte), + byteValue$Byte(Kind.Byte), + valueOf$Short(Kind.Short), + shortValue$Short(Kind.Short), + valueOf$Char(Kind.Char), + charValue$Char(Kind.Char), + valueOf$Int(Kind.Int), + intValue$Int(Kind.Int), + valueOf$Long(Kind.Long), + longValue$Long(Kind.Long), + valueOf$Float(Kind.Float), + floatValue$Float(Kind.Float), + valueOf$Double(Kind.Double), + doubleValue$Double(Kind.Double); + + BoxingPlugin(Kind kind) { + assert name().startsWith("valueOf$") || name().startsWith(kind.getJavaName() + "Value$"); + this.kind = kind; + this.box = name().charAt(0) == 'v'; + } + + private final Kind kind; + private final boolean box; + + public final boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + if (box) { + ResolvedJavaType resultType = builder.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); + builder.push(Kind.Object, builder.append(new BoxNode(args[0], resultType, kind))); + } else { + builder.push(kind, builder.append(new UnboxNode(args[0], kind))); + } + return true; + } + + public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) { + Class[] parameterTypes = box ? new Class[]{kind.toJavaClass()} : new Class[0]; + return GraphBuilderPlugin.resolveTarget(metaAccess, kind.toBoxedJavaClass(), name(), parameterTypes); + } + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.java; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Used by a {@link GraphBuilderPlugin} to interface with a graph builder object. + */ +public interface GraphBuilderContext { + + T append(T fixed); + + T append(T fixed); + + T append(T fixed); + + T append(T v); + + StampProvider getStampProvider(); + + MetaAccessProvider getMetaAccess(); + + Assumptions getAssumptions(); + + void push(Kind kind, ValueNode value); +} diff -r 684612ee6abb -r 5e33637f5e5a 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 Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Feb 03 11:10:24 2015 +0100 @@ -47,6 +47,7 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; @@ -58,20 +59,26 @@ public class GraphBuilderPhase extends BasePhase { private final GraphBuilderConfiguration graphBuilderConfig; + private final GraphBuilderPlugins graphBuilderPlugins; - public GraphBuilderPhase(GraphBuilderConfiguration graphBuilderConfig) { - this.graphBuilderConfig = graphBuilderConfig; + public GraphBuilderPhase(GraphBuilderConfiguration config) { + this.graphBuilderConfig = config; + this.graphBuilderPlugins = new GraphBuilderPlugins(); } @Override protected void run(StructuredGraph graph, HighTierContext context) { - new Instance(context.getMetaAccess(), graphBuilderConfig, context.getOptimisticOptimizations()).run(graph); + new Instance(context.getMetaAccess(), context.getStampProvider(), context.getAssumptions(), graphBuilderConfig, graphBuilderPlugins, context.getOptimisticOptimizations()).run(graph); } public GraphBuilderConfiguration getGraphBuilderConfig() { return graphBuilderConfig; } + public GraphBuilderPlugins getGraphBuilderPlugins() { + return graphBuilderPlugins; + } + public static class Instance extends Phase { protected StructuredGraph currentGraph; @@ -81,7 +88,10 @@ private ResolvedJavaMethod rootMethod; private final GraphBuilderConfiguration graphBuilderConfig; + private final GraphBuilderPlugins graphBuilderPlugins; private final OptimisticOptimizations optimisticOpts; + private final StampProvider stampProvider; + private final Assumptions assumptions; /** * Gets the graph being processed by this builder. @@ -90,13 +100,21 @@ return currentGraph; } - public Instance(MetaAccessProvider metaAccess, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { + public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, + OptimisticOptimizations optimisticOpts) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; this.metaAccess = metaAccess; + this.stampProvider = stampProvider; + this.assumptions = assumptions; + this.graphBuilderPlugins = graphBuilderPlugins; assert metaAccess != null; } + public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { + this(metaAccess, stampProvider, assumptions, graphBuilderConfig, null, optimisticOpts); + } + @Override protected void run(StructuredGraph graph) { ResolvedJavaMethod method = graph.method(); @@ -143,7 +161,7 @@ } } - public class BytecodeParser extends AbstractBytecodeParser { + public class BytecodeParser extends AbstractBytecodeParser implements GraphBuilderContext { private BciBlock[] loopHeaders; private LocalLiveness liveness; @@ -752,38 +770,53 @@ args[0] = TypeProfileProxyNode.proxify(args[0], profile); } } + if (GraalOptions.InlineDuringParsing.getValue() && invokeKind.isDirect()) { - if (GraalOptions.InlineDuringParsing.getValue() && invokeKind.isDirect() && targetMethod.canBeInlined() && targetMethod.hasBytecodes()) { - if (targetMethod.getCode().length <= GraalOptions.TrivialInliningSize.getValue() && currentDepth < GraalOptions.InlineDuringParsingMaxDepth.getValue() && - graphBuilderConfig.shouldInlineTrivial()) { - BytecodeParser parser = new BytecodeParser(metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, StructuredGraph.INVOCATION_ENTRY_BCI); - final FrameState[] lazyFrameState = new FrameState[1]; - HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(targetMethod, currentGraph, () -> { - if (lazyFrameState[0] == null) { - lazyFrameState[0] = frameState.create(bci()); + if (graphBuilderPlugins != null) { + GraphBuilderPlugin plugin = graphBuilderPlugins.getPlugin(targetMethod); + if (plugin != null) { + int beforeStackSize = frameState.stackSize; + if (plugin.handleInvocation(this, args)) { + // System.out.println("used plugin: " + plugin); + assert beforeStackSize + resultType.getSlotCount() == frameState.stackSize; + return; } - return lazyFrameState[0]; - }); - startFrameState.initializeFromArgumentsArray(args); - parser.build(currentDepth + 1, this.lastInstr, startFrameState); + assert beforeStackSize == frameState.stackSize; + } + } - FixedWithNextNode calleeBeforeReturnNode = parser.getBeforeReturnNode(); - this.lastInstr = calleeBeforeReturnNode; - if (calleeBeforeReturnNode != null) { - ValueNode calleeReturnValue = parser.getReturnValue(); - if (calleeReturnValue != null) { - frameState.push(calleeReturnValue.getKind().getStackKind(), calleeReturnValue); - } - } + if (targetMethod.canBeInlined() && targetMethod.hasBytecodes()) { + if (targetMethod.getCode().length <= GraalOptions.TrivialInliningSize.getValue() && currentDepth < GraalOptions.InlineDuringParsingMaxDepth.getValue() && + graphBuilderConfig.shouldInlineTrivial()) { + BytecodeParser parser = new BytecodeParser(metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, StructuredGraph.INVOCATION_ENTRY_BCI); + final FrameState[] lazyFrameState = new FrameState[1]; + HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(targetMethod, currentGraph, () -> { + if (lazyFrameState[0] == null) { + lazyFrameState[0] = frameState.create(bci()); + } + return lazyFrameState[0]; + }); + startFrameState.initializeFromArgumentsArray(args); + parser.build(currentDepth + 1, this.lastInstr, startFrameState); - FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode(); - if (calleeBeforeUnwindNode != null) { - ValueNode calleeUnwindValue = parser.getUnwindValue(); - assert calleeUnwindValue != null; - calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci())); + FixedWithNextNode calleeBeforeReturnNode = parser.getBeforeReturnNode(); + this.lastInstr = calleeBeforeReturnNode; + if (calleeBeforeReturnNode != null) { + ValueNode calleeReturnValue = parser.getReturnValue(); + if (calleeReturnValue != null) { + frameState.push(calleeReturnValue.getKind().getStackKind(), calleeReturnValue); + } + } + + FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode(); + if (calleeBeforeUnwindNode != null) { + ValueNode calleeUnwindValue = parser.getUnwindValue(); + assert calleeUnwindValue != null; + calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci())); + } + + return; } - - return; } } @@ -937,7 +970,7 @@ throw GraalInternalError.shouldNotReachHere("Can not append Node of type: " + v.getClass().getName()); } - private T append(T fixed) { + public T append(T fixed) { assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; T added = currentGraph.add(fixed); @@ -946,7 +979,7 @@ return added; } - private T append(T fixed) { + public T append(T fixed) { assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; T added = currentGraph.add(fixed); @@ -955,7 +988,7 @@ return added; } - protected T append(T fixed) { + public T append(T fixed) { assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; T added = currentGraph.add(fixed); @@ -964,7 +997,7 @@ return added; } - private T append(T v) { + public T append(T v) { assert !(v instanceof ConstantNode); T added = currentGraph.unique(v); return added; @@ -1456,6 +1489,22 @@ append(ifNode); } + public StampProvider getStampProvider() { + return stampProvider; + } + + public MetaAccessProvider getMetaAccess() { + return metaAccess; + } + + public Assumptions getAssumptions() { + return assumptions; + } + + public void push(Kind kind, ValueNode value) { + frameState.push(kind, value); + } + } } } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.nodes.*; + +/** + * Extensions for handling certain bytecode instructions while building a + * {@linkplain StructuredGraph graph} from a bytecode stream. + */ +public interface GraphBuilderPlugin { + + /** + * Processes an invocation parsed in a bytecode stream and add nodes to a graph being + * constructed that implement the semantics of the invocation. + * + * @param builder object being used to build a graph + * @param args the arguments to the invocation + */ + boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args); + + /** + * Gets the method handled by {@link #handleInvocation(GraphBuilderContext, ValueNode[])} . + */ + ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess); + + /** + * Looks up a {@link ResolvedJavaMethod}. + * + * @param methodNameBase the name of the method is the prefix of this value up to the first '$' + * character + */ + static ResolvedJavaMethod resolveTarget(MetaAccessProvider metaAccess, Class declaringClass, String methodNameBase, Class... parameterTypes) { + int index = methodNameBase.indexOf('$'); + String methodName = index == -1 ? methodNameBase : methodNameBase.substring(0, index); + try { + return metaAccess.lookupJavaMethod(methodName.equals("") ? declaringClass.getDeclaredConstructor(parameterTypes) : declaringClass.getDeclaredMethod(methodName, parameterTypes)); + } catch (NoSuchMethodException | SecurityException e) { + throw new GraalInternalError(e); + } + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.java; + +import java.util.*; +import java.util.stream.*; + +import com.oracle.graal.api.meta.*; + +/** + * A repository of {@link GraphBuilderPlugin}s. + */ +public class GraphBuilderPlugins { + + private final Map map = new HashMap<>(); + + /** + * Registers all the constants of an enum that implements {@link GraphBuilderPlugin}. + */ + public & GraphBuilderPlugin> void register(MetaAccessProvider metaAccess, Class enumClass) { + assert Enum.class.isAssignableFrom(enumClass); + Object[] enumConstants = enumClass.getEnumConstants(); + for (Object o : enumConstants) { + GraphBuilderPlugin gbp = (GraphBuilderPlugin) o; + ResolvedJavaMethod target = gbp.getInvocationTarget(metaAccess); + GraphBuilderPlugin oldValue = map.put(target, gbp); + // System.out.println("registered: " + gbp); + assert oldValue == null; + } + } + + /** + * Gets the plugin for a given method registered in the object. + * + * @param method the method to lookup + * @return the plugin associated with {@code method} or {@code null} if none exists + */ + public GraphBuilderPlugin getPlugin(ResolvedJavaMethod method) { + return map.get(method); + } + + @Override + public String toString() { + return map.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", ")); + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPluginsProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPluginsProvider.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; + +/** + * Interface for providers of {@link GraphBuilderPlugin}s. + */ +public interface GraphBuilderPluginsProvider extends Service { + /** + * Registers the plugins provided by this object with a plugins registry. + * + * @param plugins registry of plugins + */ + void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins); +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInsertionBuffer.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInsertionBuffer.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInsertionBuffer.java Tue Feb 03 11:10:24 2015 +0100 @@ -48,7 +48,8 @@ * index into lir list where "count" ops should be inserted indexAndCount[i * 2 + 1]: the number * of ops to be inserted at index */ - private final List indexAndCount; + private int[] indexAndCount; + private int indexAndCountSize; /** * The LIROps to be inserted. @@ -56,8 +57,8 @@ private final List ops; public LIRInsertionBuffer() { - indexAndCount = new ArrayList<>(8); - ops = new ArrayList<>(8); + indexAndCount = new int[8]; + ops = new ArrayList<>(4); } /** @@ -65,7 +66,7 @@ */ public void init(List newLir) { assert !initialized() : "already initialized"; - assert indexAndCount.size() == 0 && ops.size() == 0; + assert indexAndCountSize == 0 && ops.size() == 0; this.lir = newLir; } @@ -126,32 +127,38 @@ } ipIndex--; } - indexAndCount.clear(); + indexAndCountSize = 0; ops.clear(); } lir = null; } private void appendNew(int index, int count) { - indexAndCount.add(index); - indexAndCount.add(count); + int oldSize = indexAndCountSize; + int newSize = oldSize + 2; + if (newSize > this.indexAndCount.length) { + indexAndCount = Arrays.copyOf(indexAndCount, newSize * 2); + } + indexAndCount[oldSize] = index; + indexAndCount[oldSize + 1] = count; + this.indexAndCountSize = newSize; } private void setCountAt(int i, int value) { - indexAndCount.set((i << 1) + 1, value); + indexAndCount[(i << 1) + 1] = value; } private int numberOfInsertionPoints() { - assert indexAndCount.size() % 2 == 0 : "must have a count for each index"; - return indexAndCount.size() >> 1; + assert indexAndCount.length % 2 == 0 : "must have a count for each index"; + return indexAndCountSize >> 1; } private int indexAt(int i) { - return indexAndCount.get((i << 1)); + return indexAndCount[(i << 1)]; } private int countAt(int i) { - return indexAndCount.get((i << 1) + 1); + return indexAndCount[(i << 1) + 1]; } private boolean verify() { diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopPeelingPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopPeelingPhase.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012, 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.loop.phases; + +import java.util.function.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.loop.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.graph.*; + +public class LoopPeelingPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + if (graph.hasLoops()) { + ToDoubleFunction probabilities = new FixedNodeProbabilityCache(); + LoopsData data = new LoopsData(graph); + for (LoopEx loop : data.outerFirst()) { + if (LoopPolicies.shouldPeel(loop, probabilities)) { + Debug.log("Peeling %s", loop); + LoopTransformations.peel(loop); + Debug.dump(graph, "After peeling %s", loop); + } + } + data.deleteUnusedNodes(); + } + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java Sat Jan 31 15:51:54 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2012, 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.loop.phases; - -import static com.oracle.graal.compiler.common.GraalOptions.*; - -import java.util.function.*; - -import com.oracle.graal.debug.*; -import com.oracle.graal.loop.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.graph.*; - -public class LoopTransformHighPhase extends Phase { - - @Override - protected void run(StructuredGraph graph) { - if (graph.hasLoops()) { - if (LoopPeeling.getValue()) { - ToDoubleFunction probabilities = new FixedNodeProbabilityCache(); - LoopsData data = new LoopsData(graph); - for (LoopEx loop : data.outerFirst()) { - if (LoopPolicies.shouldPeel(loop, probabilities)) { - Debug.log("Peeling %s", loop); - LoopTransformations.peel(loop); - Debug.dump(graph, "After peeling %s", loop); - } - } - data.deleteUnusedNodes(); - } - } - } -} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java Sat Jan 31 15:51:54 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2012, 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.loop.phases; - -import static com.oracle.graal.compiler.common.GraalOptions.*; - -import java.util.*; - -import com.oracle.graal.debug.*; -import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.graph.*; -import com.oracle.graal.loop.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; - -public class LoopTransformLowPhase extends Phase { - - private static final DebugMetric UNSWITCHED = Debug.metric("Unswitched"); - private static final DebugMetric UNSWITCH_CANDIDATES = Debug.metric("UnswitchCandidates"); - - @Override - protected void run(StructuredGraph graph) { - if (graph.hasLoops()) { - if (ReassociateInvariants.getValue()) { - final LoopsData dataReassociate = new LoopsData(graph); - try (Scope s = Debug.scope("ReassociateInvariants")) { - for (LoopEx loop : dataReassociate.loops()) { - loop.reassociateInvariants(); - } - } catch (Throwable e) { - throw Debug.handle(e); - } - dataReassociate.deleteUnusedNodes(); - } - if (LoopUnswitch.getValue()) { - boolean unswitched; - do { - unswitched = false; - final LoopsData dataUnswitch = new LoopsData(graph); - for (LoopEx loop : dataUnswitch.loops()) { - if (LoopPolicies.shouldTryUnswitch(loop)) { - List controlSplits = LoopTransformations.findUnswitchable(loop); - if (controlSplits != null) { - UNSWITCH_CANDIDATES.increment(); - if (LoopPolicies.shouldUnswitch(loop, controlSplits)) { - if (Debug.isLogEnabled()) { - logUnswitch(loop, controlSplits); - } - LoopTransformations.unswitch(loop, controlSplits); - UNSWITCHED.increment(); - unswitched = true; - break; - } - } - } - } - } while (unswitched); - } - } - } - - private static void logUnswitch(LoopEx loop, List controlSplits) { - StringBuilder sb = new StringBuilder("Unswitching "); - sb.append(loop).append(" at "); - for (ControlSplitNode controlSplit : controlSplits) { - sb.append(controlSplit).append(" ["); - NodePosIterator it = controlSplit.successors().iterator(); - while (it.hasNext()) { - sb.append(controlSplit.probability((AbstractBeginNode) it.next())); - if (it.hasNext()) { - sb.append(", "); - } - } - sb.append("]"); - } - Debug.log("%s", sb); - } -} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopUnswitchingPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopUnswitchingPhase.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2012, 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.loop.phases; + +import java.util.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.loop.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; + +public class LoopUnswitchingPhase extends Phase { + + private static final DebugMetric UNSWITCHED = Debug.metric("Unswitched"); + private static final DebugMetric UNSWITCH_CANDIDATES = Debug.metric("UnswitchCandidates"); + + @Override + protected void run(StructuredGraph graph) { + if (graph.hasLoops()) { + boolean unswitched; + do { + unswitched = false; + final LoopsData dataUnswitch = new LoopsData(graph); + for (LoopEx loop : dataUnswitch.loops()) { + if (LoopPolicies.shouldTryUnswitch(loop)) { + List controlSplits = LoopTransformations.findUnswitchable(loop); + if (controlSplits != null) { + UNSWITCH_CANDIDATES.increment(); + if (LoopPolicies.shouldUnswitch(loop, controlSplits)) { + if (Debug.isLogEnabled()) { + logUnswitch(loop, controlSplits); + } + LoopTransformations.unswitch(loop, controlSplits); + UNSWITCHED.increment(); + unswitched = true; + break; + } + } + } + } + } while (unswitched); + } + } + + private static void logUnswitch(LoopEx loop, List controlSplits) { + StringBuilder sb = new StringBuilder("Unswitching "); + sb.append(loop).append(" at "); + for (ControlSplitNode controlSplit : controlSplits) { + sb.append(controlSplit).append(" ["); + NodePosIterator it = controlSplit.successors().iterator(); + while (it.hasNext()) { + sb.append(controlSplit.probability((AbstractBeginNode) it.next())); + if (it.hasNext()) { + sb.append(", "); + } + } + sb.append("]"); + } + Debug.log("%s", sb); + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/ReassociateInvariantPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/ReassociateInvariantPhase.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.loop.phases; + +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.loop.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; + +public class ReassociateInvariantPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + if (graph.hasLoops()) { + final LoopsData dataReassociate = new LoopsData(graph); + try (Scope s = Debug.scope("ReassociateInvariants")) { + for (LoopEx loop : dataReassociate.loops()) { + loop.reassociateInvariants(); + } + } catch (Throwable e) { + throw Debug.handle(e); + } + dataReassociate.deleteUnusedNodes(); + } + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Tue Feb 03 11:10:24 2015 +0100 @@ -42,7 +42,7 @@ this.direct = direct; } - private boolean direct; + private final boolean direct; public boolean hasReceiver() { return this != Static; diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/ControlFlowAnchorNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/ControlFlowAnchorNode.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.debug; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * This node prevents control flow optimizations. It is never duplicated or merged with other + * control flow anchors. + */ +@NodeInfo +public class ControlFlowAnchorNode extends FixedWithNextNode implements LIRLowerable { + + private static class Unique { + } + + protected Unique unique; + + public ControlFlowAnchorNode(@SuppressWarnings("unused") Invoke invoke) { + super(StampFactory.forVoid()); + this.unique = new Unique(); + } + + public void generate(NodeLIRBuilderTool generator) { + // do nothing + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Tue Feb 03 11:10:24 2015 +0100 @@ -56,27 +56,31 @@ gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(getValue())); } + /** + * Determines if the compiler should emit code to test whether a given object has a finalizer + * that must be registered with the runtime upon object initialization. + */ + public static boolean mayHaveFinalizer(ValueNode object, Assumptions assumptions) { + ObjectStamp objectStamp = (ObjectStamp) object.stamp(); + if (objectStamp.isExactType()) { + return objectStamp.type().hasFinalizer(); + } else if (objectStamp.type() != null && !objectStamp.type().hasFinalizableSubclass()) { + // if either the declared type of receiver or the holder + // can be assumed to have no finalizers + if (assumptions.useOptimisticAssumptions()) { + assumptions.recordNoFinalizableSubclassAssumption(objectStamp.type()); + return false; + } + } + return true; + } + @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { if (!(forValue.stamp() instanceof ObjectStamp)) { return this; } - - ObjectStamp objectStamp = (ObjectStamp) forValue.stamp(); - - boolean needsCheck = true; - if (objectStamp.isExactType()) { - needsCheck = objectStamp.type().hasFinalizer(); - } else if (objectStamp.type() != null && !objectStamp.type().hasFinalizableSubclass()) { - // if either the declared type of receiver or the holder - // can be assumed to have no finalizers - if (tool.assumptions().useOptimisticAssumptions()) { - tool.assumptions().recordNoFinalizableSubclassAssumption(objectStamp.type()); - needsCheck = false; - } - } - - if (!needsCheck) { + if (!mayHaveFinalizer(forValue, tool.assumptions())) { return null; } diff -r 684612ee6abb -r 5e33637f5e5a 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 Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Tue Feb 03 11:10:24 2015 +0100 @@ -641,177 +641,210 @@ @Override protected void node(FixedNode node) { if (node instanceof AbstractBeginNode) { - AbstractBeginNode begin = (AbstractBeginNode) node; - Node pred = node.predecessor(); + processAbstractBegin((AbstractBeginNode) node); + } else if (node instanceof FixedGuardNode) { + processFixedGuard((FixedGuardNode) node); + } else if (node instanceof CheckCastNode) { + processCheckCast((CheckCastNode) node); + } else if (node instanceof ConditionAnchorNode) { + processConditionAnchor((ConditionAnchorNode) node); + } else if (node instanceof IfNode) { + processIf((IfNode) node); + } else if (node instanceof AbstractEndNode) { + processAbstractEnd((AbstractEndNode) node); + } else if (node instanceof Invoke) { + processInvoke((Invoke) node); + } + } - if (pred != null) { - registerControlSplitInfo(pred, begin); - } - - // First eliminate any guards which can be trivially removed and register any - // type constraints the guards produce. - for (GuardNode guard : begin.guards().snapshot()) { - eliminateTrivialGuardOrRegisterStamp(guard); - } + private void processIf(IfNode ifNode) { + LogicNode compare = ifNode.condition(); - // Collect the guards which have produced conditional stamps. - // XXX (gd) IdentityHashMap.values().contains performs a linear search - // so we prefer to build a set - Set provers = Node.newSet(); - for (GuardedStamp e : state.valueConstraints.values()) { - provers.add(e.getGuard()); - } - - // Process the remaining guards. Guards which produced some type constraint should - // just be registered since they aren't trivially deleteable. Test the other guards - // to see if they can be deleted using type constraints. - for (GuardNode guard : begin.guards().snapshot()) { - if (provers.contains(guard) || !(tryReplaceWithExistingGuard(guard) || testImpliedGuard(guard))) { - registerCondition(!guard.isNegated(), guard.condition(), guard); + LogicNode replacement = null; + GuardingNode replacementAnchor = null; + AbstractBeginNode survivingSuccessor = null; + if (state.trueConditions.containsKey(compare)) { + replacement = trueConstant; + replacementAnchor = state.trueConditions.get(compare); + survivingSuccessor = ifNode.trueSuccessor(); + } else if (state.falseConditions.containsKey(compare)) { + replacement = falseConstant; + replacementAnchor = state.falseConditions.get(compare); + survivingSuccessor = ifNode.falseSuccessor(); + } else { + replacement = evaluateCondition(compare, trueConstant, falseConstant); + if (replacement != null) { + if (replacement == trueConstant) { + survivingSuccessor = ifNode.trueSuccessor(); + } else { + assert replacement == falseConstant; + survivingSuccessor = ifNode.falseSuccessor(); } } - for (GuardNode guard : provers) { - assert !testImpliedGuard(guard) : "provers shouldn't be trivially eliminatable"; - } - } else if (node instanceof FixedGuardNode) { - FixedGuardNode guard = (FixedGuardNode) node; - GuardingNode existingGuard = guard.isNegated() ? state.falseConditions.get(guard.condition()) : state.trueConditions.get(guard.condition()); - if (existingGuard != null && existingGuard instanceof FixedGuardNode) { - guard.replaceAtUsages(existingGuard.asNode()); - guard.graph().removeFixed(guard); - } else { - registerCondition(!guard.isNegated(), guard.condition(), guard); - } - } else if (node instanceof CheckCastNode) { - CheckCastNode checkCast = (CheckCastNode) node; - ValueNode object = checkCast.object(); - boolean isNull = state.isNull(object); - ResolvedJavaType type = state.getNodeType(object); - if (isNull || (type != null && checkCast.type().isAssignableFrom(type))) { - boolean nonNull = state.isNonNull(object); - GuardingNode replacementAnchor = null; - if (nonNull) { - replacementAnchor = searchAnchor(GraphUtil.unproxify(object), type); - } - if (replacementAnchor == null) { - replacementAnchor = AbstractBeginNode.prevBegin(checkCast); - } - PiNode piNode; - if (isNull) { - ConstantNode nullObject = ConstantNode.defaultForKind(Kind.Object, graph); - piNode = graph.unique(new PiNode(nullObject, nullObject.stamp(), replacementAnchor.asNode())); - } else { - piNode = graph.unique(new PiNode(object, StampFactory.declaredTrusted(type, nonNull), replacementAnchor.asNode())); - } - checkCast.replaceAtUsages(piNode); - graph.removeFixed(checkCast); - metricCheckCastRemoved.increment(); - } - } else if (node instanceof ConditionAnchorNode) { - ConditionAnchorNode conditionAnchorNode = (ConditionAnchorNode) node; - LogicNode condition = conditionAnchorNode.condition(); - GuardingNode replacementAnchor = null; - if (conditionAnchorNode.isNegated()) { - if (state.falseConditions.containsKey(condition)) { - replacementAnchor = state.falseConditions.get(condition); - } - } else { - if (state.trueConditions.containsKey(condition)) { - replacementAnchor = state.trueConditions.get(condition); - } - } - if (replacementAnchor != null) { - conditionAnchorNode.replaceAtUsages(replacementAnchor.asNode()); - conditionAnchorNode.graph().removeFixed(conditionAnchorNode); - } - } else if (node instanceof IfNode) { - IfNode ifNode = (IfNode) node; - LogicNode compare = ifNode.condition(); + } + + if (replacement != null) { + trySimplify(ifNode, compare, replacement, replacementAnchor, survivingSuccessor); + } + } - LogicNode replacement = null; - GuardingNode replacementAnchor = null; - AbstractBeginNode survivingSuccessor = null; - if (state.trueConditions.containsKey(compare)) { - replacement = trueConstant; - replacementAnchor = state.trueConditions.get(compare); - survivingSuccessor = ifNode.trueSuccessor(); - } else if (state.falseConditions.containsKey(compare)) { - replacement = falseConstant; - replacementAnchor = state.falseConditions.get(compare); - survivingSuccessor = ifNode.falseSuccessor(); + private void trySimplify(IfNode ifNode, LogicNode compare, LogicNode replacement, GuardingNode replacementAnchor, AbstractBeginNode survivingSuccessor) { + if (replacementAnchor != null && !(replacementAnchor instanceof AbstractBeginNode)) { + ValueAnchorNode anchor = graph.add(new ValueAnchorNode(replacementAnchor.asNode())); + graph.addBeforeFixed(ifNode, anchor); + } + boolean canSimplify = true; + for (Node n : survivingSuccessor.usages().snapshot()) { + if (n instanceof GuardNode || n instanceof ProxyNode) { + // Keep wired to the begin node. } else { - replacement = evaluateCondition(compare, trueConstant, falseConstant); - if (replacement != null) { - if (replacement == trueConstant) { - survivingSuccessor = ifNode.trueSuccessor(); - } else { - assert replacement == falseConstant; - survivingSuccessor = ifNode.falseSuccessor(); - } - } - } - - if (replacement != null) { - if (replacementAnchor != null && !(replacementAnchor instanceof AbstractBeginNode)) { - ValueAnchorNode anchor = graph.add(new ValueAnchorNode(replacementAnchor.asNode())); - graph.addBeforeFixed(ifNode, anchor); + if (replacementAnchor == null) { + // Cannot simplify this IfNode as there is no anchor. + canSimplify = false; + break; } - for (Node n : survivingSuccessor.usages().snapshot()) { - if (n instanceof GuardNode || n instanceof ProxyNode) { - // Keep wired to the begin node. - } else { - if (replacementAnchor == null) { - // Cannot simplify this IfNode as there is no anchor. - return; - } - // Rewire to the replacement anchor. - n.replaceFirstInput(survivingSuccessor, replacementAnchor.asNode()); - } - } + // Rewire to the replacement anchor. + n.replaceFirstInput(survivingSuccessor, replacementAnchor.asNode()); + } + } + + if (canSimplify) { + ifNode.setCondition(replacement); + if (compare.hasNoUsages()) { + GraphUtil.killWithUnusedFloatingInputs(compare); + } + } + } - ifNode.setCondition(replacement); - if (compare.hasNoUsages()) { - GraphUtil.killWithUnusedFloatingInputs(compare); - } - } - } else if (node instanceof AbstractEndNode) { - AbstractEndNode endNode = (AbstractEndNode) node; - for (PhiNode phi : endNode.merge().phis()) { - int index = endNode.merge().phiPredecessorIndex(endNode); - ValueNode value = phi.valueAt(index); - if (value instanceof ConditionalNode) { - ConditionalNode materialize = (ConditionalNode) value; - LogicNode compare = materialize.condition(); - ValueNode replacement = evaluateCondition(compare, materialize.trueValue(), materialize.falseValue()); - - if (replacement != null) { - phi.setValueAt(index, replacement); - if (materialize.hasNoUsages()) { - GraphUtil.killWithUnusedFloatingInputs(materialize); + private void processInvoke(Invoke invoke) { + if (invoke.callTarget() instanceof MethodCallTargetNode) { + MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); + ValueNode receiver = callTarget.receiver(); + if (receiver != null && callTarget.invokeKind().isIndirect()) { + ResolvedJavaType type = state.getNodeType(receiver); + if (!Objects.equals(type, StampTool.typeOrNull(receiver))) { + ResolvedJavaMethod method = type.resolveConcreteMethod(callTarget.targetMethod(), invoke.getContextType()); + if (method != null) { + if (method.canBeStaticallyBound() || type.isFinal()) { + callTarget.setInvokeKind(InvokeKind.Special); + callTarget.setTargetMethod(method); } } } } - } else if (node instanceof Invoke) { - Invoke invoke = (Invoke) node; - if (invoke.callTarget() instanceof MethodCallTargetNode) { - MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); - ValueNode receiver = callTarget.receiver(); - if (receiver != null && callTarget.invokeKind().isIndirect()) { - ResolvedJavaType type = state.getNodeType(receiver); - if (!Objects.equals(type, StampTool.typeOrNull(receiver))) { - ResolvedJavaMethod method = type.resolveConcreteMethod(callTarget.targetMethod(), invoke.getContextType()); - if (method != null) { - if (method.canBeStaticallyBound() || type.isFinal()) { - callTarget.setInvokeKind(InvokeKind.Special); - callTarget.setTargetMethod(method); - } - } + } + } + + private void processAbstractEnd(AbstractEndNode endNode) { + for (PhiNode phi : endNode.merge().phis()) { + int index = endNode.merge().phiPredecessorIndex(endNode); + ValueNode value = phi.valueAt(index); + if (value instanceof ConditionalNode) { + ConditionalNode materialize = (ConditionalNode) value; + LogicNode compare = materialize.condition(); + ValueNode replacement = evaluateCondition(compare, materialize.trueValue(), materialize.falseValue()); + + if (replacement != null) { + phi.setValueAt(index, replacement); + if (materialize.hasNoUsages()) { + GraphUtil.killWithUnusedFloatingInputs(materialize); } } } + } + } + private void processConditionAnchor(ConditionAnchorNode conditionAnchorNode) { + LogicNode condition = conditionAnchorNode.condition(); + GuardingNode replacementAnchor = null; + if (conditionAnchorNode.isNegated()) { + if (state.falseConditions.containsKey(condition)) { + replacementAnchor = state.falseConditions.get(condition); + } + } else { + if (state.trueConditions.containsKey(condition)) { + replacementAnchor = state.trueConditions.get(condition); + } } + if (replacementAnchor != null) { + conditionAnchorNode.replaceAtUsages(replacementAnchor.asNode()); + conditionAnchorNode.graph().removeFixed(conditionAnchorNode); + } + } + + private void processCheckCast(CheckCastNode checkCast) { + ValueNode object = checkCast.object(); + boolean isNull = state.isNull(object); + ResolvedJavaType type = state.getNodeType(object); + if (isNull || (type != null && checkCast.type().isAssignableFrom(type))) { + boolean nonNull = state.isNonNull(object); + GuardingNode replacementAnchor = null; + if (nonNull) { + replacementAnchor = searchAnchor(GraphUtil.unproxify(object), type); + } + if (replacementAnchor == null) { + replacementAnchor = AbstractBeginNode.prevBegin(checkCast); + } + PiNode piNode; + if (isNull) { + ConstantNode nullObject = ConstantNode.defaultForKind(Kind.Object, graph); + piNode = graph.unique(new PiNode(nullObject, nullObject.stamp(), replacementAnchor.asNode())); + } else { + piNode = graph.unique(new PiNode(object, StampFactory.declaredTrusted(type, nonNull), replacementAnchor.asNode())); + } + checkCast.replaceAtUsages(piNode); + graph.removeFixed(checkCast); + metricCheckCastRemoved.increment(); + } + } + + private void processFixedGuard(FixedGuardNode guard) { + GuardingNode existingGuard = guard.isNegated() ? state.falseConditions.get(guard.condition()) : state.trueConditions.get(guard.condition()); + if (existingGuard != null && existingGuard instanceof FixedGuardNode) { + guard.replaceAtUsages(existingGuard.asNode()); + guard.graph().removeFixed(guard); + } else { + registerCondition(!guard.isNegated(), guard.condition(), guard); + } + } + + private void processAbstractBegin(AbstractBeginNode begin) { + Node pred = begin.predecessor(); + + if (pred != null) { + registerControlSplitInfo(pred, begin); + } + + // First eliminate any guards which can be trivially removed and register any + // type constraints the guards produce. + for (GuardNode guard : begin.guards().snapshot()) { + eliminateTrivialGuardOrRegisterStamp(guard); + } + + // Collect the guards which have produced conditional stamps. + // XXX (gd) IdentityHashMap.values().contains performs a linear search + // so we prefer to build a set + Set provers = Node.newSet(); + for (GuardedStamp e : state.valueConstraints.values()) { + provers.add(e.getGuard()); + } + + // Process the remaining guards. Guards which produced some type constraint should + // just be registered since they aren't trivially deleteable. Test the other guards + // to see if they can be deleted using type constraints. + for (GuardNode guard : begin.guards().snapshot()) { + if (provers.contains(guard) || !(tryReplaceWithExistingGuard(guard) || testImpliedGuard(guard))) { + registerCondition(!guard.isNegated(), guard.condition(), guard); + } + } + assert assertImpliedGuard(provers); + } + + private boolean assertImpliedGuard(Set provers) { + for (GuardNode guard : provers) { + assert !testImpliedGuard(guard) : "provers shouldn't be trivially eliminatable"; + } + return true; } private GuardingNode searchAnchor(ValueNode value, ResolvedJavaType type) { diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Feb 03 11:10:24 2015 +0100 @@ -1068,7 +1068,13 @@ } private void addToLatestSorting(ValueNode i, SortState state) { - if (i == null || state.isVisited(i) || cfg.getNodeToBlock().get(i) != state.currentBlock() || i instanceof PhiNode || i instanceof ProxyNode) { + if (i == null || state.isVisited(i) || cfg.getNodeToBlock().get(i) != state.currentBlock() || i instanceof PhiNode) { + return; + } + + if (i instanceof ProxyNode) { + ProxyNode proxyNode = (ProxyNode) i; + addToLatestSorting(proxyNode.value(), state); return; } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalDirectivesSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalDirectivesSubstitutions.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements; + +import com.oracle.graal.api.directives.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.debug.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; + +@ClassSubstitution(GraalDirectives.class) +public class GraalDirectivesSubstitutions { + + @MethodSubstitution(forced = true) + public static void deoptimize() { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter); + } + + @MethodSubstitution(forced = true) + public static void deoptimizeAndInvalidate() { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter); + } + + @MethodSubstitution(forced = true) + public static boolean inCompiledCode() { + return true; + } + + @MacroSubstitution(forced = true, macro = ControlFlowAnchorNode.class) + public static native void controlFlowAnchor(); + + @MethodSubstitution(forced = true) + public static boolean injectBranchProbability(double probability, boolean condition) { + return BranchProbabilityNode.probability(probability, condition); + } + + @MethodSubstitution(forced = true) + public static void blackhole(boolean value) { + BlackholeNode.consume(value); + } + + @MethodSubstitution(forced = true) + public static void blackhole(byte value) { + BlackholeNode.consume(value); + } + + @MethodSubstitution(forced = true) + public static void blackhole(short value) { + BlackholeNode.consume(value); + } + + @MethodSubstitution(forced = true) + public static void blackhole(char value) { + BlackholeNode.consume(value); + } + + @MethodSubstitution(forced = true) + public static void blackhole(int value) { + BlackholeNode.consume(value); + } + + @MethodSubstitution(forced = true) + public static void blackhole(long value) { + BlackholeNode.consume(value); + } + + @MethodSubstitution(forced = true) + public static void blackhole(float value) { + BlackholeNode.consume(value); + } + + @MethodSubstitution(forced = true) + public static void blackhole(double value) { + BlackholeNode.consume(value); + } + + @MethodSubstitution(forced = true) + public static void blackhole(Object value) { + BlackholeNode.consume(value); + } + + @MethodSubstitution(forced = true) + public static boolean opaque(boolean value) { + return OpaqueNode.opaque(value); + } + + @MethodSubstitution(forced = true) + public static byte opaque(byte value) { + return OpaqueNode.opaque(value); + } + + @MethodSubstitution(forced = true) + public static short opaque(short value) { + return OpaqueNode.opaque(value); + } + + @MethodSubstitution(forced = true) + public static char opaque(char value) { + return OpaqueNode.opaque(value); + } + + @MethodSubstitution(forced = true) + public static int opaque(int value) { + return OpaqueNode.opaque(value); + } + + @MethodSubstitution(forced = true) + public static long opaque(long value) { + return OpaqueNode.opaque(value); + } + + @MethodSubstitution(forced = true) + public static float opaque(float value) { + return OpaqueNode.opaque(value); + } + + @MethodSubstitution(forced = true) + public static double opaque(double value) { + return OpaqueNode.opaque(value); + } + + @MethodSubstitution(forced = true) + public static T opaque(T value) { + return OpaqueNode.opaque(value); + } +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Tue Feb 03 11:10:24 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.util.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.directives.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; @@ -47,6 +48,7 @@ public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { BoxingSubstitutions.registerReplacements(replacements); + replacements.registerSubstitutions(GraalDirectives.class, GraalDirectivesSubstitutions.class); if (Intrinsify.getValue()) { replacements.registerSubstitutions(Arrays.class, ArraysSubstitutions.class); replacements.registerSubstitutions(Array.class, ArraySubstitutions.class); @@ -60,18 +62,18 @@ replacements.registerSubstitutions(Short.class, ShortSubstitutions.class); replacements.registerSubstitutions(UnsignedMath.class, UnsignedMathSubstitutions.class); replacements.registerSubstitutions(Edges.class, EdgesSubstitutions.class); - if (Options.UseBlackholeSubstitution.getValue()) { - replacements.registerSubstitutions(new Type() { - public String getTypeName() { - return "org.openjdk.jmh.infra.Blackhole"; - } - }, BlackholeSubstitutions.class); - replacements.registerSubstitutions(new Type() { - public String getTypeName() { - return "org.openjdk.jmh.logic.BlackHole"; - } - }, BlackholeSubstitutions.class); - } + } + if (Options.UseBlackholeSubstitution.getValue()) { + replacements.registerSubstitutions(new Type() { + public String getTypeName() { + return "org.openjdk.jmh.infra.Blackhole"; + } + }, BlackholeSubstitutions.class); + replacements.registerSubstitutions(new Type() { + public String getTypeName() { + return "org.openjdk.jmh.logic.BlackHole"; + } + }, BlackholeSubstitutions.class); } } } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Tue Feb 03 11:10:24 2015 +0100 @@ -113,11 +113,13 @@ } String originalName = originalName(substituteMethod, methodSubstitution.value()); JavaSignature originalSignature = originalSignature(substituteMethod, methodSubstitution.signature(), methodSubstitution.isStatic()); - Executable originalMethod = originalMethod(classSubstitution, methodSubstitution.optional(), originalName, originalSignature); - if (originalMethod != null && (guard == null || guard.execute())) { - ResolvedJavaMethod original = registerMethodSubstitution(this, originalMethod, substituteMethod); - if (original != null && methodSubstitution.forced() && shouldIntrinsify(original)) { - forcedSubstitutions.add(original); + Executable[] originalMethods = originalMethods(classSubstitution, methodSubstitution.optional(), originalName, originalSignature); + for (Executable originalMethod : originalMethods) { + if (originalMethod != null && (guard == null || guard.execute())) { + ResolvedJavaMethod original = registerMethodSubstitution(this, originalMethod, substituteMethod); + if (original != null && methodSubstitution.forced() && shouldIntrinsify(original)) { + forcedSubstitutions.add(original); + } } } } @@ -126,11 +128,13 @@ if (macroSubstitution != null && (defaultGuard == null || defaultGuard.execute())) { String originalName = originalName(substituteMethod, macroSubstitution.value()); JavaSignature originalSignature = originalSignature(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic()); - Executable originalMethod = originalMethod(classSubstitution, macroSubstitution.optional(), originalName, originalSignature); - if (originalMethod != null) { - ResolvedJavaMethod original = registerMacroSubstitution(this, originalMethod, macroSubstitution.macro()); - if (original != null && macroSubstitution.forced() && shouldIntrinsify(original)) { - forcedSubstitutions.add(original); + Executable[] originalMethods = originalMethods(classSubstitution, macroSubstitution.optional(), originalName, originalSignature); + for (Executable originalMethod : originalMethods) { + if (originalMethod != null) { + ResolvedJavaMethod original = registerMacroSubstitution(this, originalMethod, macroSubstitution.macro()); + if (original != null && macroSubstitution.forced() && shouldIntrinsify(original)) { + forcedSubstitutions.add(original); + } } } } @@ -159,20 +163,30 @@ return new JavaSignature(returnType, parameters); } - private Executable originalMethod(ClassSubstitution classSubstitution, boolean optional, String name, JavaSignature signature) { + private Executable[] originalMethods(ClassSubstitution classSubstitution, boolean optional, String name, JavaSignature signature) { Class originalClass = classSubstitution.value(); if (originalClass == ClassSubstitution.class) { + ArrayList result = new ArrayList<>(); for (String className : classSubstitution.className()) { originalClass = resolveClass(className, classSubstitution.optional()); if (originalClass != null) { - break; + result.add(lookupOriginalMethod(originalClass, name, signature, optional)); } } - if (originalClass == null) { + if (result.size() == 0) { // optional class was not found return null; } + return result.toArray(new Executable[result.size()]); } + Executable original = lookupOriginalMethod(originalClass, name, signature, optional); + if (original != null) { + return new Executable[]{original}; + } + return null; + } + + private Executable lookupOriginalMethod(Class originalClass, String name, JavaSignature signature, boolean optional) throws GraalInternalError { try { if (name.equals("")) { assert signature.returnType.equals(void.class) : signature; @@ -605,7 +619,8 @@ if (MethodsElidedInSnippets != null && methodToParse.getSignature().getReturnKind() == Kind.Void && MethodFilter.matches(MethodsElidedInSnippets, methodToParse)) { graph.addAfterFixed(graph.start(), graph.add(new ReturnNode(null))); } else { - createGraphBuilder(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph); + createGraphBuilder(metaAccess, replacements.providers.getStampProvider(), replacements.assumptions, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply( + graph); } afterParsing(graph); @@ -618,8 +633,9 @@ return graph; } - protected Instance createGraphBuilder(MetaAccessProvider metaAccess, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { - return new GraphBuilderPhase.Instance(metaAccess, graphBuilderConfig, optimisticOpts); + protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, GraphBuilderConfiguration graphBuilderConfig, + OptimisticOptimizations optimisticOpts) { + return new GraphBuilderPhase.Instance(metaAccess, stampProvider, assumptions, graphBuilderConfig, optimisticOpts); } protected void afterParsing(StructuredGraph graph) { diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BlackholeNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BlackholeNode.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BlackholeNode.java Tue Feb 03 11:10:24 2015 +0100 @@ -43,47 +43,29 @@ } @NodeIntrinsic - @SuppressWarnings("unused") - public static void consume(boolean v) { - } + public static native void consume(boolean v); @NodeIntrinsic - @SuppressWarnings("unused") - public static void consume(byte v) { - } + public static native void consume(byte v); @NodeIntrinsic - @SuppressWarnings("unused") - public static void consume(short v) { - } + public static native void consume(short v); @NodeIntrinsic - @SuppressWarnings("unused") - public static void consume(char v) { - } + public static native void consume(char v); @NodeIntrinsic - @SuppressWarnings("unused") - public static void consume(int v) { - } + public static native void consume(int v); @NodeIntrinsic - @SuppressWarnings("unused") - public static void consume(long v) { - } + public static native void consume(long v); @NodeIntrinsic - @SuppressWarnings("unused") - public static void consume(float v) { - } + public static native void consume(float v); @NodeIntrinsic - @SuppressWarnings("unused") - public static void consume(double v) { - } + public static native void consume(double v); @NodeIntrinsic - @SuppressWarnings("unused") - public static void consume(Object v) { - } + public static native void consume(Object v); } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java Tue Feb 03 11:10:24 2015 +0100 @@ -25,12 +25,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -/** - * This is an extension of {@link MacroNode} that is a {@link StateSplit} and a - * {@link MemoryCheckpoint}. - */ @NodeInfo public class MathPowNode extends MacroStateSplitNode implements Canonicalizable.Binary { diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/OpaqueNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/OpaqueNode.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.nodes; + +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; + +@NodeInfo +public class OpaqueNode extends FloatingNode implements LIRLowerable { + + @Input ValueNode value; + + public OpaqueNode(ValueNode value) { + super(value.stamp().unrestricted()); + this.value = value; + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + gen.setResult(this, gen.operand(value)); + } + + @NodeIntrinsic + public static native boolean opaque(boolean v); + + @NodeIntrinsic + public static native byte opaque(byte v); + + @NodeIntrinsic + public static native short opaque(short v); + + @NodeIntrinsic + public static native char opaque(char v); + + @NodeIntrinsic + public static native int opaque(int v); + + @NodeIntrinsic + public static native long opaque(long v); + + @NodeIntrinsic + public static native float opaque(float v); + + @NodeIntrinsic + public static native double opaque(double v); + + @NodeIntrinsic + public static native T opaque(T v); +} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Tue Feb 03 11:10:24 2015 +0100 @@ -177,12 +177,12 @@ Suites suites = suitesProvider.createSuites(); removeInliningPhase(suites); StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), new Assumptions(false), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); PhaseSuite graphBuilderSuite = getGraphBuilderSuite(suitesProvider); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); CompilationResultBuilderFactory factory = getOptimizedCallTargetInstrumentationFactory(backend.getTarget().arch.getName(), javaMethod); - return compileGraph(graph, null, cc, javaMethod, providers, backend, providers.getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, getProfilingInfo(graph), null, + return compileGraph(graph, cc, javaMethod, providers, backend, providers.getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, getProfilingInfo(graph), null, suites, new CompilationResult(), factory); } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Tue Feb 03 11:10:24 2015 +0100 @@ -137,49 +137,20 @@ HighTierContext tierContext = new HighTierContext(providers, assumptions, graphCache, new PhaseSuite(), OptimisticOptimizations.NONE); // EA frame and clean up. - try (Scope pe = Debug.scope("TrufflePartialEscape", graph)) { - new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext); - new IncrementalCanonicalizerPhase<>(canonicalizer, new ConditionalEliminationPhase()).apply(graph, tierContext); - } catch (Throwable t) { - Debug.handle(t); - } - - // to make frame propagations visible retry expandTree - while (expandTree(graph, assumptions, expansionLogger)) { + do { try (Scope pe = Debug.scope("TrufflePartialEscape", graph)) { new PartialEscapePhase(true, canonicalizer).apply(graph, tierContext); new IncrementalCanonicalizerPhase<>(canonicalizer, new ConditionalEliminationPhase()).apply(graph, tierContext); } catch (Throwable t) { Debug.handle(t); } - } + } while (expandTree(graph, assumptions, expansionLogger)); if (expansionLogger != null) { expansionLogger.print(callTarget); } - for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) { - Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage()); - throw GraphUtil.approxSourceException(neverPartOfCompilationNode, exception); - } - - new VerifyNoIntrinsicsLeftPhase().apply(graph, false); - for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) { - materializeNode.replaceAtUsages(materializeNode.getFrame()); - graph.removeFixed(materializeNode); - } - for (VirtualObjectNode virtualObjectNode : graph.getNodes(VirtualObjectNode.class)) { - if (virtualObjectNode instanceof VirtualOnlyInstanceNode) { - VirtualOnlyInstanceNode virtualOnlyInstanceNode = (VirtualOnlyInstanceNode) virtualObjectNode; - virtualOnlyInstanceNode.setAllowMaterialization(true); - } else if (virtualObjectNode instanceof VirtualInstanceNode) { - VirtualInstanceNode virtualInstanceNode = (VirtualInstanceNode) virtualObjectNode; - ResolvedJavaType type = virtualInstanceNode.type(); - if (type.getAnnotation(CompilerDirectives.ValueType.class) != null) { - virtualInstanceNode.setIdentity(false); - } - } - } + postPartialEvaluation(graph); } catch (Throwable e) { throw Debug.handle(e); @@ -188,6 +159,26 @@ return graph; } + private static void postPartialEvaluation(final StructuredGraph graph) { + NeverPartOfCompilationNode.verifyNotFoundIn(graph); + for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) { + materializeNode.replaceAtUsages(materializeNode.getFrame()); + graph.removeFixed(materializeNode); + } + for (VirtualObjectNode virtualObjectNode : graph.getNodes(VirtualObjectNode.class)) { + if (virtualObjectNode instanceof VirtualOnlyInstanceNode) { + VirtualOnlyInstanceNode virtualOnlyInstanceNode = (VirtualOnlyInstanceNode) virtualObjectNode; + virtualOnlyInstanceNode.setAllowMaterialization(true); + } else if (virtualObjectNode instanceof VirtualInstanceNode) { + VirtualInstanceNode virtualInstanceNode = (VirtualInstanceNode) virtualObjectNode; + ResolvedJavaType type = virtualInstanceNode.type(); + if (type.getAnnotation(CompilerDirectives.ValueType.class) != null) { + virtualInstanceNode.setIdentity(false); + } + } + } + } + private void injectConstantCallTarget(final StructuredGraph graph, final OptimizedCallTarget constantCallTarget, PhaseContext baseContext) { ParameterNode thisNode = graph.getParameter(0); diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCacheImpl.java Tue Feb 03 11:10:24 2015 +0100 @@ -94,13 +94,13 @@ public StructuredGraph createInlineGraph(String name) { StructuredGraph graph = new StructuredGraph(name, callInlinedMethod); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), config, TruffleCompilerImpl.Optimizations).apply(graph); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), config, TruffleCompilerImpl.Optimizations).apply(graph); return graph; } public StructuredGraph createRootGraph(String name) { StructuredGraph graph = new StructuredGraph(name, callRootMethod); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), configForRoot, TruffleCompilerImpl.Optimizations).apply(graph); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), configForRoot, TruffleCompilerImpl.Optimizations).apply(graph); return graph; } @@ -294,7 +294,7 @@ protected StructuredGraph parseGraph(final ResolvedJavaMethod method, final PhaseContext phaseContext) { final StructuredGraph graph = new StructuredGraph(method); - new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), config, optimisticOptimizations).apply(graph); + new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), phaseContext.getStampProvider(), phaseContext.getAssumptions(), config, optimisticOptimizations).apply(graph); return graph; } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Tue Feb 03 11:10:24 2015 +0100 @@ -153,7 +153,7 @@ CodeCacheProvider codeCache = providers.getCodeCache(); CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false); CompilationResult compilationResult = new CompilationResult(name); - result = compileGraph(graph, null, cc, graph.method(), providers, backend, codeCache.getTarget(), null, createGraphBuilderSuite(), Optimizations, getProfilingInfo(graph), speculationLog, + result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, createGraphBuilderSuite(), Optimizations, getProfilingInfo(graph), speculationLog, suites, compilationResult, CompilationResultBuilderFactory.Default); } catch (Throwable e) { throw Debug.handle(e); diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Tue Feb 03 11:10:24 2015 +0100 @@ -176,5 +176,8 @@ @Option(help = "Print additional more verbose Truffle compilation statistics at the end of a run.", type = OptionType.Debug) public static final OptionValue TruffleCompilationStatisticDetails = new OptionValue<>(false); + + @Option(help = "Experimental new version of the partial evaluator.", type = OptionType.Debug) + public static final OptionValue FastPE = new OptionValue<>(false); // @formatter:on } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInlining.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInlining.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleInlining.java Tue Feb 03 11:10:24 2015 +0100 @@ -144,7 +144,12 @@ } public TruffleInliningDecision findByCall(OptimizedDirectCallNode callNode) { - return getCallSites().stream().filter(c -> c.getProfile().getCallNode() == callNode).findFirst().orElse(null); + for (TruffleInliningDecision d : getCallSites()) { + if (d.getProfile().getCallNode() == callNode) { + return d; + } + } + return null; } /** diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Sat Jan 31 15:51:54 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Tue Feb 03 11:10:24 2015 +0100 @@ -25,6 +25,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.replacements.nodes.*; @NodeInfo @@ -44,4 +45,11 @@ public final String getMessage() { return message + " " + arguments.toString(); } + + public static void verifyNotFoundIn(final StructuredGraph graph) { + for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) { + Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage()); + throw GraphUtil.approxSourceException(neverPartOfCompilationNode, exception); + } + } } diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java Sat Jan 31 15:51:54 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.truffle.phases; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.nodes.frame.*; - -/** - * Verification phase for checking that no frame intrinsic nodes introduced by the - * {@link PartialEvaluator} are still in the graph. - */ -public class VerifyNoIntrinsicsLeftPhase extends Phase { - - @Override - protected void run(StructuredGraph graph) { - verifyNoInstanceLeft(graph, NewFrameNode.class); - } - - public static void verifyNoInstanceLeft(StructuredGraph graph, Class clazz) { - if (graph.getNodes(clazz).count() != 0) { - throw new VerificationError("Found unexpected node(s): %s", graph.getNodes(clazz)); - } - } -} diff -r 684612ee6abb -r 5e33637f5e5a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java Tue Feb 03 11:10:24 2015 +0100 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.substitutions; + +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.truffle.nodes.frame.*; +import com.oracle.truffle.api.*; + +/** + * Provider of {@link GraphBuilderPlugin}s for Truffle classes. + */ +@ServiceProvider(GraphBuilderPluginsProvider.class) +public class TruffleGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { + public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + plugins.register(metaAccess, CompilerDirectivesPlugin.class); + } + + /** + * Plugins for {@link CompilerDirectives}. + */ + enum CompilerDirectivesPlugin implements GraphBuilderPlugin { + inInterpreter() { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + builder.append(ConstantNode.forBoolean(false)); + return true; + } + }, + inCompiledCode() { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + builder.append(ConstantNode.forBoolean(true)); + return true; + } + }, + transferToInterpreter() { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + builder.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); + return true; + } + }, + transferToInterpreterAndInvalidate() { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + builder.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); + return true; + } + }, + interpreterOnly(Runnable.class) { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + return true; + } + }, + interpreterOnly$(Callable.class) { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + return true; + } + }, + injectBranchProbability(double.class, boolean.class) { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + ValueNode probability = args[0]; + ValueNode condition = args[1]; + builder.append(new BranchProbabilityNode(probability, condition)); + return true; + } + }, + bailout(String.class) { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + // TODO: is this too eager? Should a BailoutNode be created instead? + ValueNode message = args[0]; + if (message.isConstant()) { + throw new BailoutException(message.asConstant().toValueString()); + } + throw new BailoutException("bailout (message is not compile-time constant, so no additional information is available)"); + } + }, + + isCompilationConstant(Object.class) { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + ValueNode arg0 = args[0]; + if (arg0 instanceof BoxNode) { + arg0 = ((BoxNode) arg0).getValue(); + } + if (arg0.isConstant()) { + builder.push(Kind.Boolean, builder.append(ConstantNode.forBoolean(true))); + return true; + } + + // Cannot create MacroNodes in a plugin (yet) + return false; + } + }, + materialize(Object.class) { + public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + builder.append(new ForceMaterializeNode(args[0])); + return true; + } + }; + + CompilerDirectivesPlugin(Class... parameterTypes) { + this.parameterTypes = parameterTypes; + } + + private final Class[] parameterTypes; + + public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) { + return GraphBuilderPlugin.resolveTarget(metaAccess, CompilerDirectives.class, name(), parameterTypes); + } + } +} diff -r 684612ee6abb -r 5e33637f5e5a mx/mx_graal.py --- a/mx/mx_graal.py Sat Jan 31 15:51:54 2015 +0100 +++ b/mx/mx_graal.py Tue Feb 03 11:10:24 2015 +0100 @@ -1360,7 +1360,7 @@ if not containsF: jmhArgs += ['-f1'] - # find all projects with the JMH dependency + # find all projects with a direct JMH dependency jmhProjects = [] for p in mx.projects(): if 'JMH' in p.deps: diff -r 684612ee6abb -r 5e33637f5e5a mx/suite.py --- a/mx/suite.py Sat Jan 31 15:51:54 2015 +0100 +++ b/mx/suite.py Tue Feb 03 11:10:24 2015 +0100 @@ -220,6 +220,25 @@ "workingSets" : "API,Graal", }, + "com.oracle.graal.api.directives" : { + "subDir" : "graal", + "sourceDirs" : ["src"], + "checkstyle" : "com.oracle.graal.graph", + "javaCompliance" : "1.8", + "workingSets" : "API,Graal", + }, + + "com.oracle.graal.api.directives.test" : { + "subDir" : "graal", + "sourceDirs" : ["src"], + "checkstyle" : "com.oracle.graal.graph", + "dependencies" : [ + "com.oracle.graal.compiler.test", + ], + "javaCompliance" : "1.8", + "workingSets" : "API,Graal", + }, + "com.oracle.graal.api.runtime" : { "subDir" : "graal", "sourceDirs" : ["src"], @@ -582,6 +601,7 @@ "subDir" : "graal", "sourceDirs" : ["src"], "dependencies" : [ + "com.oracle.graal.api.directives", "com.oracle.graal.compiler", "com.oracle.graal.java", "com.oracle.graal.word", @@ -798,6 +818,7 @@ "com.oracle.graal.phases", ], "checkstyle" : "com.oracle.graal.graph", + "annotationProcessors" : ["com.oracle.graal.service.processor"], "javaCompliance" : "1.8", "workingSets" : "Graal,Java", }, @@ -854,6 +875,7 @@ "subDir" : "graal", "sourceDirs" : ["src"], "dependencies" : [ + "com.oracle.graal.api.directives", "com.oracle.graal.test", "com.oracle.graal.printer", "com.oracle.graal.runtime",