# HG changeset patch # User Christian Haeubl # Date 1353587414 -3600 # Node ID 8d16b9b2c51e220579a0733d74a61cdd8624af07 # Parent 0d7dfa5b79e8d70801ca4e4c453259263ef81999 first part of refactoring the InliningPhase added control-flow sensitive inlining inlining requires an Assumption object so that HotSpot can keep track of the inlined methods diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Assumptions.java Thu Nov 22 13:30:14 2012 +0100 @@ -167,8 +167,12 @@ * Array with the assumptions. This field is directly accessed from C++ code in the Graal/HotSpot implementation. */ private Assumption[] list; + private boolean useOptimisticAssumptions; + private int count; - private int count; + public Assumptions(boolean useOptimisticAssumptions) { + this.useOptimisticAssumptions = useOptimisticAssumptions; + } /** * Returns whether any assumptions have been registered. @@ -178,6 +182,10 @@ return count == 0; } + public boolean useOptimisticAssumptions() { + return useOptimisticAssumptions; + } + @Override public Iterator iterator() { return new Iterator() { @@ -203,9 +211,9 @@ * @param receiverType the type that is assumed to have no finalizable subclasses * @return {@code true} if the assumption was recorded and can be assumed; {@code false} otherwise */ - @SuppressWarnings("static-method") public boolean recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) { // TODO (thomaswue): Record that assumption correctly. + assert useOptimisticAssumptions; return false; } @@ -215,6 +223,7 @@ * @param subtype the one concrete subtype */ public void recordConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) { + assert useOptimisticAssumptions; record(new ConcreteSubtype(context, subtype)); } @@ -227,6 +236,7 @@ * @param impl the concrete method that is the only possible target for the virtual call */ public void recordConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) { + assert useOptimisticAssumptions; record(new ConcreteMethod(method, context, impl)); } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Thu Nov 22 13:30:14 2012 +0100 @@ -65,7 +65,7 @@ ResolvedJavaType uniqueSubtype = type == null ? null : type.findUniqueConcreteSubtype(); if (uniqueSubtype != null) { types = new ResolvedJavaType[] {uniqueSubtype}; - if (assumptions != null) { + if (assumptions.useOptimisticAssumptions()) { assumptions.recordConcreteSubtype(type, uniqueSubtype); exact = true; } else { diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e 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 Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -26,6 +26,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -123,13 +124,14 @@ hints.add(invoke); } - new InliningPhase(null, runtime(), hints, null, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + Assumptions assumptions = new Assumptions(false); + new InliningPhase(null, runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); Debug.dump(graph, "Graph"); new BoxingEliminationPhase().apply(graph); Debug.dump(graph, "Graph"); new ExpandBoxingNodesPhase(pool).apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph); diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -24,6 +24,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; @@ -36,10 +37,11 @@ StructuredGraph graph = parse("canonicalCompare" + i); assertEquals(referenceGraph, graph); } - new CanonicalizerPhase(null, runtime(), null).apply(referenceGraph); + Assumptions assumptions = new Assumptions(false); + new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); for (int i = 1; i < 4; i++) { StructuredGraph graph = parse("canonicalCompare" + i); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); assertEquals(referenceGraph, graph); } } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -55,7 +55,7 @@ public void test1() { Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph); new DeadCodeEliminationPhase().apply(graph); for (Node node : graph.getNodes()) { @@ -112,7 +112,7 @@ ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); StructuredGraph graph = new StructuredGraph(javaMethod); new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph); - new CanonicalizerPhase(null, runtime, null).apply(graph); + new CanonicalizerPhase(null, runtime, new Assumptions(false)).apply(graph); new DeadCodeEliminationPhase().apply(graph); for (Node node : graph.getNodes()) { diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -24,6 +24,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; @@ -81,7 +82,7 @@ for (Invoke invoke : graph.getInvokes()) { invoke.intrinsify(null); } - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); Debug.dump(referenceGraph, "Graph"); assertEquals(referenceGraph, graph); diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -24,6 +24,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -54,7 +55,7 @@ Debug.scope("FloatingReadTest", new DebugDumpScope(snippet), new Runnable() { public void run() { StructuredGraph graph = parse(snippet); - new LoweringPhase(runtime(), null).apply(graph); + new LoweringPhase(runtime(), new Assumptions(false)).apply(graph); new FloatingReadPhase().apply(graph); ReturnNode returnNode = null; diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -26,6 +26,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -85,18 +86,20 @@ for (Invoke invoke : graph.getInvokes()) { hints.add(invoke); } - new InliningPhase(null, runtime(), hints, null, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + + Assumptions assumptions = new Assumptions(false); + new InliningPhase(null, runtime(), hints, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new PhiStampPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); Debug.dump(graph, "Graph"); new BoxingEliminationPhase().apply(graph); Debug.dump(graph, "Graph"); new ExpandBoxingNodesPhase(pool).apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); - new CanonicalizerPhase(null, runtime(), null).apply(referenceGraph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); new DeadCodeEliminationPhase().apply(referenceGraph); assertEquals(referenceGraph, graph); diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -26,6 +26,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -143,7 +144,7 @@ n.replaceFirstInput(local, constant); } Debug.dump(graph, "Graph"); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -26,6 +26,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -63,8 +64,9 @@ for (Invoke invoke : graph.getInvokes()) { hints.add(invoke); } - new InliningPhase(null, runtime(), hints, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + Assumptions assumptions = new Assumptions(false); + new InliningPhase(null, runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); } } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -26,6 +26,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -73,8 +74,10 @@ for (Invoke invoke : graph.getInvokes()) { hints.add(invoke); } - new InliningPhase(null, runtime(), hints, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + + Assumptions assumptions = new Assumptions(false); + new InliningPhase(null, runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e 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 Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -24,6 +24,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.loop.phases.*; @@ -79,8 +80,9 @@ ((StateSplit) stateSplit).setStateAfter(null); } - new CanonicalizerPhase(null, runtime(), null).apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(referenceGraph); + Assumptions assumptions = new Assumptions(false); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() { @Override public void run() { diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -28,6 +28,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; @@ -91,8 +92,9 @@ for (Invoke invoke : graph.getInvokes()) { hints.add(invoke); } - new InliningPhase(null, runtime(), hints, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + Assumptions assumptions = new Assumptions(false); + new InliningPhase(null, runtime(), hints, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new DeadCodeEliminationPhase().apply(graph); return graph; } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -24,6 +24,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; @@ -241,9 +242,10 @@ private void test(String test, String ref) { StructuredGraph testGraph = parse(test); - new CanonicalizerPhase(null, runtime(), null).apply(testGraph); + Assumptions assumptions = new Assumptions(false); + new CanonicalizerPhase(null, runtime(), assumptions).apply(testGraph); StructuredGraph refGraph = parse(ref); - new CanonicalizerPhase(null, runtime(), null).apply(refGraph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(refGraph); assertEquals(testGraph, refGraph); } } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -24,6 +24,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; @@ -164,9 +165,10 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); // TypeSystemTest.outputGraph(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + Assumptions assumptions = new Assumptions(false); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new ConditionalEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph); } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -24,6 +24,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; @@ -97,7 +98,7 @@ private void testZeroReturn(String methodName) { StructuredGraph graph = parse(methodName); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph); new DeadCodeEliminationPhase().apply(graph); assertConstantReturn(graph, 0); } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -24,6 +24,7 @@ import org.junit.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; @@ -88,7 +89,7 @@ // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), new Assumptions(false)).apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -28,6 +28,7 @@ import org.junit.Test; +import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.*; @@ -189,12 +190,13 @@ if (false) { StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + Assumptions assumptions = new Assumptions(false); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new ConditionalEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new GlobalValueNumberingPhase().apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); - new CanonicalizerPhase(null, runtime(), null).apply(referenceGraph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); new GlobalValueNumberingPhase().apply(referenceGraph); assertEquals(referenceGraph, graph); } @@ -253,9 +255,10 @@ if (false) { StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + Assumptions assumptions = new Assumptions(false); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); new ConditionalEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); Debug.dump(graph, "Graph"); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext()); } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e 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 Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -26,6 +26,7 @@ import org.junit.Test; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; @@ -168,12 +169,13 @@ n.node().setProbability(100000); } - new InliningPhase(null, runtime(), null, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + Assumptions assumptions = new Assumptions(false); + new InliningPhase(null, runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new DeadCodeEliminationPhase().apply(graph); Debug.dump(graph, "Graph"); - new PartialEscapeAnalysisPhase(null, runtime(), null).apply(graph); + new PartialEscapeAnalysisPhase(null, runtime(), assumptions).apply(graph); new CullFrameStatesPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); Debug.dump(graph, "Graph"); int retCount = 0; for (ReturnNode ret : graph.getNodes(ReturnNode.class)) { diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -28,6 +28,7 @@ import org.junit.Test; +import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; @@ -153,15 +154,16 @@ for (Invoke n : graph.getInvokes()) { n.node().setProbability(100000); } - new InliningPhase(null, runtime(), null, null, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); + Assumptions assumptions = new Assumptions(false); + new InliningPhase(null, runtime(), null, assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL).apply(graph); new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); // TypeSystemTest.outputGraph(graph, "before EscapeAnalysis " + snippet); - new PartialEscapeAnalysisPhase(null, runtime(), null).apply(graph); + new PartialEscapeAnalysisPhase(null, runtime(), assumptions).apply(graph); // TypeSystemTest.outputGraph(graph, "after EscapeAnalysis " + snippet); new CullFrameStatesPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), null).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); // TypeSystemTest.outputGraph(graph, "after CullFrameStates " + snippet); return graph; } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e 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 Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Nov 22 13:30:14 2012 +0100 @@ -75,7 +75,7 @@ return Debug.scope("GraalCompiler", new Object[]{graph, method, this}, new Callable() { public CompilationResult call() { - final Assumptions assumptions = GraalOptions.OptAssumptions ? new Assumptions() : null; + final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions); final LIR lir = Debug.scope("FrontEnd", new Callable() { public LIR call() { @@ -135,7 +135,7 @@ plan.runPhases(PhasePosition.HIGH_LEVEL, graph); if (GraalOptions.FullUnroll) { - new LoopFullUnrollPhase(runtime).apply(graph); + new LoopFullUnrollPhase(runtime, assumptions).apply(graph); if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } @@ -261,7 +261,7 @@ TargetMethodAssembler tasm = backend.newAssembler(frameMap, lir); backend.emitCode(tasm, method, lir); CompilationResult targetMethod = tasm.finishTargetMethod(method, false); - if (assumptions != null && !assumptions.isEmpty()) { + if (!assumptions.isEmpty()) { targetMethod.setAssumptions(assumptions); } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu Nov 22 13:30:14 2012 +0100 @@ -29,6 +29,7 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; @@ -112,10 +113,11 @@ @Override public void run() { - VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime); - SnippetInstaller installer = new SnippetInstaller(runtime, runtime.getGraalRuntime().getTarget()); + Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions); + VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime, assumptions); + SnippetInstaller installer = new SnippetInstaller(runtime, runtime.getGraalRuntime().getTarget(), assumptions); GraalIntrinsics.installIntrinsics(installer); - runtime.installSnippets(installer); + runtime.installSnippets(installer, assumptions); } }); diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Nov 22 13:30:14 2012 +0100 @@ -199,7 +199,7 @@ protected abstract RegisterConfig createRegisterConfig(boolean globalStubConfig); - public void installSnippets(SnippetInstaller installer) { + public void installSnippets(SnippetInstaller installer, Assumptions assumptions) { installer.install(SystemSnippets.class); installer.install(UnsafeSnippets.class); installer.install(ArrayCopySnippets.class); @@ -209,10 +209,10 @@ installer.install(NewObjectSnippets.class); installer.install(MonitorSnippets.class); - checkcastSnippets = new CheckCastSnippets.Templates(this); - instanceofSnippets = new InstanceOfSnippets.Templates(this); - newObjectSnippets = new NewObjectSnippets.Templates(this, graalRuntime.getTarget(), config.useTLAB); - monitorSnippets = new MonitorSnippets.Templates(this, config.useFastLocking); + checkcastSnippets = new CheckCastSnippets.Templates(this, assumptions); + instanceofSnippets = new InstanceOfSnippets.Templates(this, assumptions); + newObjectSnippets = new NewObjectSnippets.Templates(this, assumptions, graalRuntime.getTarget(), config.useTLAB); + monitorSnippets = new MonitorSnippets.Templates(this, assumptions, config.useFastLocking); } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Thu Nov 22 13:30:14 2012 +0100 @@ -229,8 +229,8 @@ private final ResolvedJavaMethod secondary; private final ResolvedJavaMethod dynamic; - public Templates(CodeCacheProvider runtime) { - super(runtime, CheckCastSnippets.class); + public Templates(CodeCacheProvider runtime, Assumptions assumptions) { + super(runtime, assumptions, CheckCastSnippets.class); exact = snippet("checkcastExact", Object.class, Object.class, boolean.class); primary = snippet("checkcastPrimary", Object.class, Object.class, boolean.class, int.class); secondary = snippet("checkcastSecondary", Object.class, Object.class, Object[].class, boolean.class); @@ -265,7 +265,7 @@ arguments = arguments("hub", hub).add("object", object).add("hints", hints); } - SnippetTemplate template = cache.get(key); + SnippetTemplate template = cache.get(key, assumptions); Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); } @@ -282,7 +282,7 @@ Key key = new Key(dynamic).add("checkNull", checkNull); Arguments arguments = arguments("hub", hub).add("object", object); - SnippetTemplate template = cache.get(key); + SnippetTemplate template = cache.get(key, assumptions); Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); template.instantiate(runtime, checkcast, DEFAULT_REPLACER, arguments); } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Thu Nov 22 13:30:14 2012 +0100 @@ -165,8 +165,8 @@ private final ResolvedJavaMethod instanceofPrimary; private final ResolvedJavaMethod instanceofSecondary; - public Templates(CodeCacheProvider runtime) { - super(runtime, InstanceOfSnippets.class); + public Templates(CodeCacheProvider runtime, Assumptions assumptions) { + super(runtime, assumptions, InstanceOfSnippets.class); instanceofExact = snippet("instanceofExact", Object.class, Object.class, Object.class, Object.class, boolean.class); instanceofPrimary = snippet("instanceofPrimary", Object.class, Object.class, Object.class, Object.class, boolean.class, int.class); instanceofSecondary = snippet("instanceofSecondary", Object.class, Object.class, Object.class, Object.class, Object[].class, boolean.class); diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java Thu Nov 22 13:30:14 2012 +0100 @@ -36,6 +36,7 @@ public class IntrinsifyArrayCopyPhase extends Phase { private final GraalCodeCacheProvider runtime; + private final Assumptions assumptions; private ResolvedJavaMethod arrayCopy; private ResolvedJavaMethod byteArrayCopy; private ResolvedJavaMethod shortArrayCopy; @@ -46,8 +47,9 @@ private ResolvedJavaMethod doubleArrayCopy; private ResolvedJavaMethod objectArrayCopy; - public IntrinsifyArrayCopyPhase(GraalCodeCacheProvider runtime) { + public IntrinsifyArrayCopyPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) { this.runtime = runtime; + this.assumptions = assumptions; try { byteArrayCopy = getArrayCopySnippet(runtime, byte.class); charArrayCopy = getArrayCopySnippet(runtime, char.class); @@ -121,7 +123,7 @@ } } if (GraalOptions.OptCanonicalizer && hits) { - new CanonicalizerPhase(null, runtime, null).apply(graph); + new CanonicalizerPhase(null, runtime, assumptions).apply(graph); } } } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Thu Nov 22 13:30:14 2012 +0100 @@ -399,8 +399,8 @@ private final ResolvedJavaMethod checkCounter; private final boolean useFastLocking; - public Templates(CodeCacheProvider runtime, boolean useFastLocking) { - super(runtime, MonitorSnippets.class); + public Templates(CodeCacheProvider runtime, Assumptions assumptions, boolean useFastLocking) { + super(runtime, assumptions, MonitorSnippets.class); monitorenter = snippet("monitorenter", Object.class, boolean.class, boolean.class); monitorexit = snippet("monitorexit", Object.class, boolean.class); monitorenterStub = snippet("monitorenterStub", Object.class, boolean.class, boolean.class); @@ -435,7 +435,7 @@ if (!eliminated) { arguments.add("object", monitorenterNode.object()); } - SnippetTemplate template = cache.get(key); + SnippetTemplate template = cache.get(key, assumptions); Map nodes = template.instantiate(runtime, monitorenterNode, DEFAULT_REPLACER, arguments); for (Node n : nodes.values()) { if (n instanceof BeginLockScopeNode) { @@ -460,7 +460,7 @@ if (!eliminated) { arguments.add("object", monitorexitNode.object()); } - SnippetTemplate template = cache.get(key); + SnippetTemplate template = cache.get(key, assumptions); Map nodes = template.instantiate(runtime, monitorexitNode, DEFAULT_REPLACER, arguments); for (Node n : nodes.values()) { if (n instanceof EndLockScopeNode) { diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Thu Nov 22 13:30:14 2012 +0100 @@ -243,8 +243,8 @@ private final TargetDescription target; private final boolean useTLAB; - public Templates(CodeCacheProvider runtime, TargetDescription target, boolean useTLAB) { - super(runtime, NewObjectSnippets.class); + public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target, boolean useTLAB) { + super(runtime, assumptions, NewObjectSnippets.class); this.target = target; this.useTLAB = useTLAB; allocate = snippet("allocate", int.class); @@ -318,7 +318,7 @@ add("wordKind", target.wordKind). add("type", arrayType); Arguments arguments = new Arguments().add("length", lengthNode); - SnippetTemplate template = cache.get(key); + SnippetTemplate template = cache.get(key, assumptions); Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments); template.instantiate(runtime, newArrayNode, DEFAULT_REPLACER, arguments); } @@ -330,7 +330,7 @@ ValueNode size = tlabAllocateNode.size(); Key key = new Key(allocate); Arguments arguments = arguments("size", size); - SnippetTemplate template = cache.get(key); + SnippetTemplate template = cache.get(key, assumptions); Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); template.instantiate(runtime, tlabAllocateNode, DEFAULT_REPLACER, arguments); } @@ -347,7 +347,7 @@ Key key = new Key(initializeObject).add("size", size).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()); - SnippetTemplate template = cache.get(key); + SnippetTemplate template = cache.get(key, assumptions); Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); } @@ -364,7 +364,7 @@ Key key = new Key(elementKind.isObject() ? initializeObjectArray : initializePrimitiveArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("size", initializeNode.size()).add("length", initializeNode.length()); - SnippetTemplate template = cache.get(key); + SnippetTemplate template = cache.get(key, assumptions); Debug.log("Lowering initializeObjectArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); } @@ -381,7 +381,7 @@ HotSpotKlassOop hub = type.klassOop(); Key key = new Key(newmultiarray).add("dimensions", Varargs.vargargs(int.class, rank)).add("rank", rank); Arguments arguments = arguments("dimensions", dims).add("hub", hub); - SnippetTemplate template = cache.get(key); + SnippetTemplate template = cache.get(key, assumptions); template.instantiate(runtime, newmultiarrayNode, DEFAULT_REPLACER, arguments); } } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Thu Nov 22 13:30:14 2012 +0100 @@ -77,7 +77,7 @@ loop.inside().duplicate().insertBefore(loop); } - public static void fullUnroll(LoopEx loop, MetaAccessProvider runtime) { + public static void fullUnroll(LoopEx loop, MetaAccessProvider runtime, Assumptions assumptions) { //assert loop.isCounted(); //TODO (gd) strenghten : counted with known trip count int iterations = 0; LoopBeginNode loopBegin = loop.loopBegin(); @@ -85,7 +85,7 @@ while (!loopBegin.isDeleted()) { int mark = graph.getMark(); peel(loop); - new CanonicalizerPhase(null, runtime, null, mark, null).apply(graph); + new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph); if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > GraalOptions.MaximumDesiredSize * 3) { throw new BailoutException("FullUnroll : Graph seems to grow out of proportion"); } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java Thu Nov 22 13:30:14 2012 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.loop.phases; +import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; @@ -32,9 +33,11 @@ public class LoopFullUnrollPhase extends Phase { private static final DebugMetric FULLY_UNROLLED_LOOPS = Debug.metric("FullUnrolls"); private final GraalCodeCacheProvider runtime; + private final Assumptions assumptions; - public LoopFullUnrollPhase(GraalCodeCacheProvider runtime) { + public LoopFullUnrollPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) { this.runtime = runtime; + this.assumptions = assumptions; } @Override @@ -48,7 +51,7 @@ for (LoopEx loop : dataCounted.countedLoops()) { if (LoopPolicies.shouldFullUnroll(loop)) { Debug.log("FullUnroll %s", loop); - LoopTransformations.fullUnroll(loop, runtime); + LoopTransformations.fullUnroll(loop, runtime, assumptions); FULLY_UNROLLED_LOOPS.increment(); Debug.dump(graph, "After fullUnroll %s", loop); peeled = true; diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Thu Nov 22 13:30:14 2012 +0100 @@ -58,7 +58,7 @@ ResolvedJavaType exactType; if (stamp.isExactType()) { exactType = stamp.type(); - } else if (stamp.type() != null && tool.assumptions() != null) { + } else if (stamp.type() != null && tool.assumptions().useOptimisticAssumptions()) { exactType = stamp.type().findUniqueConcreteSubtype(); if (exactType != null) { tool.assumptions().recordConcreteSubtype(stamp.type(), exactType); diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e 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 Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Thu Nov 22 13:30:14 2012 +0100 @@ -62,7 +62,7 @@ needsCheck = stamp.type().hasFinalizer(); } else if (stamp.type() != null && !stamp.type().hasFinalizableSubclass()) { // if either the declared type of receiver or the holder can be assumed to have no finalizers - if (tool.assumptions() != null && tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type())) { + if (tool.assumptions().useOptimisticAssumptions() && tool.assumptions().recordNoFinalizableSubclassAssumption(stamp.type())) { needsCheck = false; } } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Thu Nov 22 13:30:14 2012 +0100 @@ -24,7 +24,6 @@ import java.lang.reflect.*; import java.util.*; -import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -37,6 +36,8 @@ import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.InliningUtil.InlineInfo; import com.oracle.graal.phases.common.InliningUtil.InliningCallback; +import com.oracle.graal.phases.common.InliningUtil.InliningPolicy; +import com.oracle.graal.phases.common.InliningUtil.WeightComputationPolicy; public class InliningPhase extends Phase implements InliningCallback { /* @@ -46,17 +47,12 @@ */ private final TargetDescription target; - private final GraalCodeCacheProvider runtime; - - private final Collection hints; - - private Assumptions assumptions; + private final PhasePlan plan; - private final PhasePlan plan; + private final GraalCodeCacheProvider runtime; + private final Assumptions assumptions; private final GraphCache cache; - private final WeightComputationPolicy weightComputationPolicy; private final InliningPolicy inliningPolicy; - private final OptimisticOptimizations optimisticOpts; // Metrics private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed"); @@ -64,97 +60,54 @@ private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize"); private static final DebugMetric metricInliningRuns = Debug.metric("Runs"); - public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Collection hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) { + public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Collection hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) { + this(target, runtime, assumptions, cache, plan, createInliningPolicy(runtime, assumptions, optimisticOpts, hints)); + } + + public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy) { this.target = target; this.runtime = runtime; - this.hints = hints; this.assumptions = assumptions; this.cache = cache; this.plan = plan; - this.optimisticOpts = optimisticOpts; - this.weightComputationPolicy = createWeightComputationPolicy(); - this.inliningPolicy = createInliningPolicy(); + this.inliningPolicy = inliningPolicy; } @Override protected void run(final StructuredGraph graph) { - NodeBitMap visitedFixedNodes = graph.createNodeBitMap(true); - Deque sortedInvokes = new ArrayDeque<>(); - - queueInvokes(graph.start(), sortedInvokes, visitedFixedNodes); + inliningPolicy.initialize(graph); - while (!sortedInvokes.isEmpty() && graph.getNodeCount() < GraalOptions.MaximumDesiredSize) { - final Invoke invoke = sortedInvokes.pop(); - if (hints != null && !hints.contains(invoke)) { - continue; - } + while (inliningPolicy.continueInlining(graph)) { + final InlineInfo candidate = inliningPolicy.next(); + if (candidate != null) { + boolean isWorthInlining = inliningPolicy.isWorthInlining(candidate); - InlineInfo candidate = Debug.scope("InliningDecisions", new Callable() { - @Override - public InlineInfo call() throws Exception { - InlineInfo info = InliningUtil.getInlineInfo(invoke, computeInliningLevel(invoke), runtime, assumptions, InliningPhase.this, optimisticOpts); - if (info == null || !info.invoke.node().isAlive() || info.level > GraalOptions.MaximumInlineLevel) { - return null; - } - metricInliningConsidered.increment(); - if (inliningPolicy.isWorthInlining(graph, info)) { - return info; - } else { - return null; + metricInliningConsidered.increment(); + if (isWorthInlining) { + int mark = graph.getMark(); + try { + candidate.inline(graph, runtime, this, assumptions); + Debug.dump(graph, "after %s", candidate); + Iterable newNodes = graph.getNewNodes(mark); + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph); + } + metricInliningPerformed.increment(); + + inliningPolicy.scanInvokes(newNodes); + } catch (BailoutException bailout) { + // TODO determine if we should really bail out of the whole compilation. + throw bailout; + } catch (AssertionError e) { + throw new GraalInternalError(e).addContext(candidate.toString()); + } catch (RuntimeException e) { + throw new GraalInternalError(e).addContext(candidate.toString()); + } catch (GraalInternalError e) { + throw e.addContext(candidate.toString()); } } - }); - - // TEMP: -// if (GraalOptions.AlwaysInlineTrivialMethods) { -// TODO: Continue; -// } - - if (candidate != null) { - int mark = graph.getMark(); - try { - FixedNode predecessor = (FixedNode) invoke.predecessor(); - candidate.inline(graph, runtime, InliningPhase.this); - Debug.dump(graph, "after %s", candidate); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph); - } - metricInliningPerformed.increment(); - - queueInvokes(predecessor, sortedInvokes, visitedFixedNodes); - } catch (BailoutException bailout) { - // TODO determine if we should really bail out of the whole compilation. - throw bailout; - } catch (AssertionError e) { - throw new GraalInternalError(e).addContext(candidate.toString()); - } catch (RuntimeException e) { - throw new GraalInternalError(e).addContext(candidate.toString()); - } catch (GraalInternalError e) { - throw e.addContext(candidate.toString()); - } } } - - if (graph.getNodeCount() >= GraalOptions.MaximumDesiredSize) { - if (GraalOptions.Debug) { - Debug.scope("InliningDecisions", new Runnable() { - public void run() { - Debug.log("inlining is cut off by MaximumDesiredSize"); - } - }); - - metricInliningStoppedByMaxDesiredSize.increment(); - } - } - } - - private static void queueInvokes(FixedNode start, Deque invokes, NodeBitMap visitedFixedNodes) { - ArrayList results = new ArrayList<>(); - new InliningIterator(start, results, visitedFixedNodes).apply(); - // insert the newly found invokes in their correct control-flow order - for (int i = results.size() - 1; i >= 0; i--) { - invokes.addFirst(results.get(i)); - } } @Override @@ -188,133 +141,63 @@ return newGraph; } - @Override - public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) { - boolean preferred = hints != null && hints.contains(invoke); - return weightComputationPolicy.computeWeight(caller, method, invoke, preferred); - } - - public static int graphComplexity(StructuredGraph graph) { - int result = 0; - for (Node node : graph.getNodes()) { - if (node instanceof ConstantNode || node instanceof LocalNode || node instanceof BeginNode || node instanceof ReturnNode || node instanceof UnwindNode) { - result += 0; - } else if (node instanceof PhiNode) { - result += 5; - } else if (node instanceof MergeNode || node instanceof Invoke || node instanceof LoopEndNode || node instanceof EndNode) { - result += 0; - } else if (node instanceof ControlSplitNode) { - result += ((ControlSplitNode) node).blockSuccessorCount(); - } else { - result += 1; - } - } - return Math.max(1, result); - } - - - @Override - public void recordConcreteMethodAssumption(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) { - assumptions.recordConcreteMethod(method, context, impl); - } - - @Override - public void recordMethodContentsAssumption(ResolvedJavaMethod method) { - if (assumptions != null) { - assumptions.recordMethodContents(method); - } + private interface InliningDecision { + boolean isWorthInlining(InlineInfo info); } - private static int computeInliningLevel(Invoke invoke) { - int count = -1; - FrameState curState = invoke.stateAfter(); - while (curState != null) { - count++; - curState = curState.outerFrameState(); - } - return count; - } - - private static InliningPolicy createInliningPolicy() { - switch(GraalOptions.InliningPolicy) { - case 0: return new WeightBasedInliningPolicy(); - case 1: return new C1StaticSizeBasedInliningPolicy(); - case 2: return new MinimumCodeSizeBasedInliningPolicy(); - case 3: return new DynamicSizeBasedInliningPolicy(); - case 4: return new GreedySizeBasedInliningPolicy(); - default: - GraalInternalError.shouldNotReachHere(); - return null; + private abstract static class AbstractInliningDecision implements InliningDecision { + public static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) { + boolean success = info.weight() <= maxSize; + if (DebugScope.getInstance().isLogEnabled()) { + String formatterString = success ? "inlining %s (size %f <= %f)" : "not inlining %s (too large %f > %f)"; + Debug.log(formatterString, InliningUtil.methodName(info), info.weight(), maxSize); + } + return success; } - } - private static WeightComputationPolicy createWeightComputationPolicy() { - switch(GraalOptions.WeightComputationPolicy) { - case 0: throw new GraalInternalError("removed because of invokation counter changes"); - case 1: return new BytecodeSizeBasedWeightComputationPolicy(); - case 2: return new ComplexityBasedWeightComputationPolicy(); - default: - GraalInternalError.shouldNotReachHere(); - return null; - } - } - - private interface InliningPolicy { - boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info); - } - - private static class WeightBasedInliningPolicy implements InliningPolicy { - @Override - public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) { - if (!checkCompiledCodeSize(info)) { + public static boolean checkCompiledCodeSize(InlineInfo info) { + if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) { + Debug.log("not inlining %s (CompiledCodeSize %d > %d)", InliningUtil.methodName(info), info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize); return false; } - - double penalty = Math.pow(GraalOptions.InliningSizePenaltyExp, callerGraph.getNodeCount() / (double) GraalOptions.MaximumDesiredSize) / GraalOptions.InliningSizePenaltyExp; - if (info.weight > GraalOptions.MaximumInlineWeight / (1 + penalty * GraalOptions.InliningSizePenalty)) { - Debug.log("not inlining %s (cut off by weight %e)", InliningUtil.methodName(info), info.weight); - return false; - } - - Debug.log("inlining %s (weight %f): %s", InliningUtil.methodName(info), info.weight); return true; } } - private static class C1StaticSizeBasedInliningPolicy implements InliningPolicy { + private static class C1StaticSizeBasedInliningDecision extends AbstractInliningDecision { @Override - public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) { - double maxSize = Math.max(GraalOptions.MaximumTrivialSize, Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * GraalOptions.MaximumInlineSize); + public boolean isWorthInlining(InlineInfo info) { + double maxSize = Math.max(GraalOptions.MaximumTrivialSize, Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize); return decideSizeBasedInlining(info, maxSize); } } - private static class MinimumCodeSizeBasedInliningPolicy implements InliningPolicy { + private static class MinimumCodeSizeBasedInliningDecision extends AbstractInliningDecision { @Override - public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) { + public boolean isWorthInlining(InlineInfo info) { assert GraalOptions.ProbabilityAnalysis; if (!checkCompiledCodeSize(info)) { return false; } - double inlineWeight = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke.probability()); - double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * GraalOptions.MaximumInlineSize * inlineWeight; + double inlineWeight = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability()); + double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize * inlineWeight; maxSize = Math.max(GraalOptions.MaximumTrivialSize, maxSize); return decideSizeBasedInlining(info, maxSize); } } - private static class DynamicSizeBasedInliningPolicy implements InliningPolicy { + private static class DynamicSizeBasedInliningDecision extends AbstractInliningDecision { @Override - public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) { + public boolean isWorthInlining(InlineInfo info) { assert GraalOptions.ProbabilityAnalysis; if (!checkCompiledCodeSize(info)) { return false; } - double inlineBoost = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke.probability()) + Math.log10(Math.max(1, info.invoke.probability() - GraalOptions.ProbabilityCapForInlining + 1)); - double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * GraalOptions.MaximumInlineSize; + double inlineBoost = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability()) + Math.log10(Math.max(1, info.invoke().probability() - GraalOptions.ProbabilityCapForInlining + 1)); + double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize; maxSize = maxSize + maxSize * inlineBoost; maxSize = Math.min(GraalOptions.MaximumGreedyInlineSize, Math.max(GraalOptions.MaximumTrivialSize, maxSize)); @@ -322,9 +205,9 @@ } } - private static class GreedySizeBasedInliningPolicy implements InliningPolicy { + private static class GreedySizeBasedInliningDecision extends AbstractInliningDecision { @Override - public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) { + public boolean isWorthInlining(InlineInfo info) { assert GraalOptions.ProbabilityAnalysis; if (!checkCompiledCodeSize(info)) { return false; @@ -332,44 +215,22 @@ double maxSize = GraalOptions.MaximumGreedyInlineSize; if (GraalOptions.InliningBonusPerTransferredValue != 0) { - Signature signature = info.invoke.methodCallTarget().targetMethod().getSignature(); - int transferredValues = signature.getParameterCount(!Modifier.isStatic(info.invoke.methodCallTarget().targetMethod().getModifiers())); + Signature signature = info.invoke().methodCallTarget().targetMethod().getSignature(); + int transferredValues = signature.getParameterCount(!Modifier.isStatic(info.invoke().methodCallTarget().targetMethod().getModifiers())); if (signature.getReturnKind() != Kind.Void) { transferredValues++; } maxSize += transferredValues * GraalOptions.InliningBonusPerTransferredValue; } - double inlineRatio = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke.probability()); - maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * maxSize * inlineRatio; + double inlineRatio = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke().probability()); + maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio; maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize); return decideSizeBasedInlining(info, maxSize); } } - private static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) { - boolean success = info.weight <= maxSize; - if (DebugScope.getInstance().isLogEnabled()) { - String formatterString = success ? "inlining %s (size %f <= %f)" : "not inlining %s (too large %f > %f)"; - Debug.log(formatterString, InliningUtil.methodName(info), info.weight, maxSize); - } - return success; - } - - private static boolean checkCompiledCodeSize(InlineInfo info) { - if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) { - Debug.log("not inlining %s (CompiledCodeSize %d > %d)", InliningUtil.methodName(info), info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize); - return false; - } - return true; - } - - - private interface WeightComputationPolicy { - double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke); - } - private static class BytecodeSizeBasedWeightComputationPolicy implements WeightComputationPolicy { @Override public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) { @@ -392,17 +253,166 @@ } } + private static class CFInliningPolicy implements InliningPolicy { + private final InliningDecision inliningDecision; + private final WeightComputationPolicy weightComputationPolicy; + private final Collection hints; + private final GraalCodeCacheProvider runtime; + private final Assumptions assumptions; + private final OptimisticOptimizations optimisticOpts; + private final Deque sortedInvokes; + private NodeBitMap visitedFixedNodes; + private FixedNode invokePredecessor; + + public CFInliningPolicy(InliningDecision inliningPolicy, WeightComputationPolicy weightComputationPolicy, Collection hints, + GraalCodeCacheProvider runtime, Assumptions assumptions, OptimisticOptimizations optimisticOpts) { + this.inliningDecision = inliningPolicy; + this.weightComputationPolicy = weightComputationPolicy; + this.hints = hints; + this.runtime = runtime; + this.assumptions = assumptions; + this.optimisticOpts = optimisticOpts; + this.sortedInvokes = new ArrayDeque<>(); + } + + public boolean continueInlining(StructuredGraph graph) { + if (graph.getNodeCount() >= GraalOptions.MaximumDesiredSize) { + InliningUtil.logInliningDecision("inlining is cut off by MaximumDesiredSize"); + metricInliningStoppedByMaxDesiredSize.increment(); + return false; + } + + return !sortedInvokes.isEmpty(); + } + + public InlineInfo next() { + Invoke invoke = sortedInvokes.pop(); + InlineInfo info = InliningUtil.getInlineInfo(invoke, runtime, assumptions, this, optimisticOpts); + if (info != null) { + invokePredecessor = (FixedNode) info.invoke().predecessor(); + } + return info; + } + + public boolean isWorthInlining(InlineInfo info) { + return inliningDecision.isWorthInlining(info); + } + + public void initialize(StructuredGraph graph) { + visitedFixedNodes = graph.createNodeBitMap(true); + scanGraphForInvokes(graph.start()); + if (hints != null) { + sortedInvokes.retainAll(hints); + } + } + + public void scanInvokes(Iterable newNodes) { + scanGraphForInvokes(invokePredecessor); + } + + private void scanGraphForInvokes(FixedNode start) { + ArrayList invokes = new InliningIterator(start, visitedFixedNodes).apply(); + + // insert the newly found invokes in their correct control-flow order + for (int i = invokes.size() - 1; i >= 0; i--) { + sortedInvokes.addFirst(invokes.get(i)); + } + } + + public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) { + boolean preferredInvoke = hints != null && hints.contains(invoke); + return weightComputationPolicy.computeWeight(caller, method, invoke, preferredInvoke); + } + } + + private static class PriorityInliningPolicy implements InliningPolicy { + private final InliningDecision inliningDecision; + private final WeightComputationPolicy weightComputationPolicy; + private final Collection hints; + private final GraalCodeCacheProvider runtime; + private final Assumptions assumptions; + private final OptimisticOptimizations optimisticOpts; + private final PriorityQueue sortedCandidates; + + public PriorityInliningPolicy(InliningDecision inliningPolicy, WeightComputationPolicy weightComputationPolicy, Collection hints, + GraalCodeCacheProvider runtime, Assumptions assumptions, OptimisticOptimizations optimisticOpts) { + this.inliningDecision = inliningPolicy; + this.weightComputationPolicy = weightComputationPolicy; + this.hints = hints; + this.runtime = runtime; + this.assumptions = assumptions; + this.optimisticOpts = optimisticOpts; + sortedCandidates = new PriorityQueue<>(); + } + + public boolean continueInlining(StructuredGraph graph) { + if (graph.getNodeCount() >= GraalOptions.MaximumDesiredSize) { + InliningUtil.logInliningDecision("inlining is cut off by MaximumDesiredSize"); + metricInliningStoppedByMaxDesiredSize.increment(); + return false; + } + + return !sortedCandidates.isEmpty(); + } + + public InlineInfo next() { + // refresh cached info before using it (it might have been in the queue for a long time) + InlineInfo info = sortedCandidates.remove(); + return InliningUtil.getInlineInfo(info.invoke(), runtime, assumptions, this, optimisticOpts); + } + + @Override + public boolean isWorthInlining(InlineInfo info) { + return inliningDecision.isWorthInlining(info); + } + + @SuppressWarnings("unchecked") + public void initialize(StructuredGraph graph) { + if (hints == null) { + scanInvokes(graph.getNodes(InvokeNode.class)); + scanInvokes(graph.getNodes(InvokeWithExceptionNode.class)); + } else { + scanInvokes((Iterable) hints); + } + } + + public void scanInvokes(Iterable nodes) { + for (Node node: nodes) { + if (node != null) { + if (node instanceof Invoke) { + Invoke invoke = (Invoke) node; + scanInvoke(invoke); + } + for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) { + scanInvoke((Invoke) usage); + } + } + } + } + + private void scanInvoke(Invoke invoke) { + InlineInfo info = InliningUtil.getInlineInfo(invoke, runtime, assumptions, this, optimisticOpts); + if (info != null) { + sortedCandidates.add(info); + } + } + + @Override + public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) { + boolean preferredInvoke = hints != null && hints.contains(invoke); + return weightComputationPolicy.computeWeight(caller, method, invoke, preferredInvoke); + } + } + private static class InliningIterator { private final FixedNode start; - private final Collection invokes; private final NodeBitMap processedNodes; private final Deque nodeQueue; private final NodeBitMap queuedNodes; - public InliningIterator(FixedNode start, Collection invokes, NodeBitMap visitedFixedNodes) { + public InliningIterator(FixedNode start, NodeBitMap visitedFixedNodes) { this.start = start; - this.invokes = invokes; this.processedNodes = visitedFixedNodes; this.nodeQueue = new ArrayDeque<>(); @@ -411,14 +421,15 @@ assert start.isAlive(); } - public void apply() { + public ArrayList apply() { + ArrayList invokes = new ArrayList<>(); FixedNode current = start; do { assert current.isAlive(); processedNodes.mark(current); if (current instanceof InvokeWithExceptionNode || current instanceof InvokeNode) { - invoke((Invoke) current); + invokes.add((Invoke) current); queueSuccessors(current); current = nextQueuedNode(); } else if (current instanceof LoopBeginNode) { @@ -448,6 +459,8 @@ assert false : current; } } while(current != null); + + return invokes; } private void queueSuccessors(FixedNode x) { @@ -485,9 +498,38 @@ } return true; } + } - protected void invoke(Invoke invoke) { - invokes.add(invoke); + private static InliningPolicy createInliningPolicy(GraalCodeCacheProvider runtime, Assumptions assumptions, OptimisticOptimizations optimisticOpts, Collection hints) { + switch(GraalOptions.InliningPolicy) { + case 0: return new CFInliningPolicy(createInliningDecision(), createWeightComputationPolicy(), hints, runtime, assumptions, optimisticOpts); + case 1: return new PriorityInliningPolicy(createInliningDecision(), createWeightComputationPolicy(), hints, runtime, assumptions, optimisticOpts); + default: + GraalInternalError.shouldNotReachHere(); + return null; + } + } + + private static InliningDecision createInliningDecision() { + switch(GraalOptions.InliningDecision) { + case 1: return new C1StaticSizeBasedInliningDecision(); + case 2: return new MinimumCodeSizeBasedInliningDecision(); + case 3: return new DynamicSizeBasedInliningDecision(); + case 4: return new GreedySizeBasedInliningDecision(); + default: + GraalInternalError.shouldNotReachHere(); + return null; + } + } + + private static WeightComputationPolicy createWeightComputationPolicy() { + switch(GraalOptions.WeightComputationPolicy) { + case 0: throw new GraalInternalError("removed because of invokation counter changes"); + case 1: return new BytecodeSizeBasedWeightComputationPolicy(); + case 2: return new ComplexityBasedWeightComputationPolicy(); + default: + GraalInternalError.shouldNotReachHere(); + return null; } } } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Thu Nov 22 13:30:14 2012 +0100 @@ -28,8 +28,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.api.meta.ResolvedJavaType.Representation; -import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -43,14 +43,23 @@ import com.oracle.graal.phases.*; public class InliningUtil { - private static final DebugMetric metricInliningTailDuplication = Debug.metric("InliningTailDuplication"); public interface InliningCallback { - StructuredGraph buildGraph(ResolvedJavaMethod method); + StructuredGraph buildGraph(final ResolvedJavaMethod method); + } + + public interface InliningPolicy { + void initialize(StructuredGraph graph); + boolean continueInlining(StructuredGraph graph); + InlineInfo next(); + void scanInvokes(Iterable newNodes); double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke); - void recordMethodContentsAssumption(ResolvedJavaMethod method); - void recordConcreteMethodAssumption(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl); + boolean isWorthInlining(InlineInfo info); + } + + public interface WeightComputationPolicy { + double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke); } public static String methodName(ResolvedJavaMethod method, Invoke invoke) { @@ -63,11 +72,31 @@ } } + public static void logInliningDecision(final String msg, final Object... args) { + if (GraalOptions.Debug) { + Debug.scope("InliningDecisions", new Runnable() { + public void run() { + Debug.log(msg, args); + } + }); + } + } + + private static InlineInfo logNotInlinedMethodAndReturnNull(final String msg, final Object... args) { + logInliningDecision(msg, args); + return null; + } + + private static boolean logNotInlinedMethodAndReturnFalse(final String msg, final Object... args) { + logInliningDecision(msg, args); + return false; + } + public static String methodName(InlineInfo info) { if (!Debug.isLogEnabled()) { return null; - } else if (info.invoke != null && info.invoke.stateAfter() != null) { - return methodName(info.invoke.stateAfter(), info.invoke.bci()) + ": " + info.toString(); + } else if (info.invoke() != null && info.invoke().stateAfter() != null) { + return methodName(info.invoke().stateAfter(), info.invoke().bci()) + ": " + info.toString(); } else { return info.toString(); } @@ -89,22 +118,44 @@ * The weight is the amortized weight of the additional code - so smaller is better. * The level is the number of nested inlinings that lead to this invoke. */ - public abstract static class InlineInfo implements Comparable { - public final Invoke invoke; - public final double weight; - public final int level; + public interface InlineInfo extends Comparable { + Invoke invoke(); + double weight(); + int level(); + int compiledCodeSize(); + int compareTo(InlineInfo o); - public InlineInfo(Invoke invoke, double weight, int level) { + /** + * Performs the inlining described by this object and returns the node that represents the return value of the + * inlined method (or null for void methods and methods that have no non-exceptional exit). + */ + void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions); + } + + public abstract static class AbstractInlineInfo implements InlineInfo { + protected final Invoke invoke; + protected final double weight; + + public AbstractInlineInfo(Invoke invoke, double weight) { this.invoke = invoke; this.weight = weight; - this.level = level; } - public abstract int compiledCodeSize(); - @Override public int compareTo(InlineInfo o) { - return (weight < o.weight) ? -1 : (weight > o.weight) ? 1 : 0; + return (weight < o.weight()) ? -1 : (weight > o.weight()) ? 1 : 0; + } + + public Invoke invoke() { + return invoke; + } + + public double weight() { + return weight; + } + + public int level() { + return computeInliningLevel(invoke); } protected static StructuredGraph getGraph(final Invoke invoke, final ResolvedJavaMethod concrete, final GraalCodeCacheProvider runtime, final InliningCallback callback) { @@ -120,36 +171,24 @@ } }); } - - public abstract boolean canDeopt(); - - /** - * Performs the inlining described by this object and returns the node that represents the return value of the - * inlined method (or null for void methods and methods that have no non-exceptional exit). - * - * @param graph - * @param runtime - * @param callback - */ - public abstract void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback); } /** * Represents an inlining opportunity where the compiler can statically determine a monomorphic target method and * therefore is able to determine the called method exactly. */ - private static class ExactInlineInfo extends InlineInfo { + private static class ExactInlineInfo extends AbstractInlineInfo { public final ResolvedJavaMethod concrete; - public ExactInlineInfo(Invoke invoke, double weight, int level, ResolvedJavaMethod concrete) { - super(invoke, weight, level); + public ExactInlineInfo(Invoke invoke, double weight, ResolvedJavaMethod concrete) { + super(invoke, weight); this.concrete = concrete; } @Override - public void inline(StructuredGraph compilerGraph, GraalCodeCacheProvider runtime, final InliningCallback callback) { + public void inline(StructuredGraph compilerGraph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) { StructuredGraph graph = getGraph(invoke, concrete, runtime, callback); - callback.recordMethodContentsAssumption(concrete); + assumptions.recordMethodContents(concrete); InliningUtil.inline(invoke, graph, true); } @@ -162,23 +201,18 @@ public String toString() { return "exact " + MetaUtil.format("%H.%n(%p):%r", concrete); } - - @Override - public boolean canDeopt() { - return false; - } } /** * Represents an inlining opportunity for which profiling information suggests a monomorphic receiver, but for which * the receiver type cannot be proven. A type check guard will be generated if this inlining is performed. */ - private static class TypeGuardInlineInfo extends InlineInfo { + private static class TypeGuardInlineInfo extends AbstractInlineInfo { public final ResolvedJavaMethod concrete; public final ResolvedJavaType type; - public TypeGuardInlineInfo(Invoke invoke, double weight, int level, ResolvedJavaMethod concrete, ResolvedJavaType type) { - super(invoke, weight, level); + public TypeGuardInlineInfo(Invoke invoke, double weight, ResolvedJavaMethod concrete, ResolvedJavaType type) { + super(invoke, weight); this.concrete = concrete; this.type = type; } @@ -189,7 +223,7 @@ } @Override - public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) { + public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) { // receiver null check must be before the type check InliningUtil.receiverNullCheck(invoke); ValueNode receiver = invoke.methodCallTarget().receiver(); @@ -208,7 +242,7 @@ graph.addBeforeFixed(invoke.node(), anchor); StructuredGraph calleeGraph = getGraph(invoke, concrete, runtime, callback); - callback.recordMethodContentsAssumption(concrete); + assumptions.recordMethodContents(concrete); InliningUtil.inline(invoke, calleeGraph, false); } @@ -216,26 +250,21 @@ public String toString() { return "type-checked " + MetaUtil.format("%H.%n(%p):%r", concrete); } - - @Override - public boolean canDeopt() { - return true; - } } /** * Polymorphic inlining of m methods with n type checks (n >= m) in case that the profiling information suggests a reasonable * amounts of different receiver types and different methods. If an unknown type is encountered a deoptimization is triggered. */ - private static class MultiTypeGuardInlineInfo extends InlineInfo { + private static class MultiTypeGuardInlineInfo extends AbstractInlineInfo { public final List concretes; public final ProfiledType[] ptypes; public final int[] typesToConcretes; public final double notRecordedTypeProbability; - public MultiTypeGuardInlineInfo(Invoke invoke, double weight, int level, List concretes, ProfiledType[] ptypes, + public MultiTypeGuardInlineInfo(Invoke invoke, double weight, List concretes, ProfiledType[] ptypes, int[] typesToConcretes, double notRecordedTypeProbability) { - super(invoke, weight, level); + super(invoke, weight); assert concretes.size() > 0 && concretes.size() <= ptypes.length : "must have at least one method but no more than types methods"; assert ptypes.length == typesToConcretes.length : "array lengths must match"; @@ -255,16 +284,16 @@ } @Override - public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) { + public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) { int numberOfMethods = concretes.size(); boolean hasReturnValue = invoke.node().kind() != Kind.Void; // receiver null check must be the first node InliningUtil.receiverNullCheck(invoke); if (numberOfMethods > 1 || shouldFallbackToInvoke()) { - inlineMultipleMethods(graph, runtime, callback, numberOfMethods, hasReturnValue); + inlineMultipleMethods(graph, runtime, callback, assumptions, numberOfMethods, hasReturnValue); } else { - inlineSingleMethod(graph, runtime, callback); + inlineSingleMethod(graph, runtime, callback, assumptions); } } @@ -272,7 +301,7 @@ return notRecordedTypeProbability > 0; } - private void inlineMultipleMethods(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, int numberOfMethods, boolean hasReturnValue) { + private void inlineMultipleMethods(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions, int numberOfMethods, boolean hasReturnValue) { FixedNode continuation = invoke.next(); ValueNode originalReceiver = invoke.methodCallTarget().receiver(); @@ -340,7 +369,7 @@ for (int i = 0; i < numberOfMethods; i++) { ResolvedJavaMethod concrete = concretes.get(i); calleeGraphs[i] = getGraph(invoke, concrete, runtime, callback); - callback.recordMethodContentsAssumption(concrete); + assumptions.recordMethodContents(concrete); } // replace the invoke with a switch on the type of the actual receiver @@ -422,7 +451,7 @@ return commonType; } - private void inlineSingleMethod(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) { + private void inlineSingleMethod(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) { assert concretes.size() == 1 && ptypes.length > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0; BeginNode calleeEntryNode = graph.add(new BeginNode()); @@ -440,7 +469,7 @@ ResolvedJavaMethod concrete = concretes.get(0); StructuredGraph calleeGraph = getGraph(invoke, concrete, runtime, callback); - callback.recordMethodContentsAssumption(concrete); + assumptions.recordMethodContents(concrete); InliningUtil.inline(invoke, calleeGraph, false); } @@ -532,11 +561,6 @@ } return builder.toString(); } - - @Override - public boolean canDeopt() { - return true; - } } @@ -547,74 +571,61 @@ private static class AssumptionInlineInfo extends ExactInlineInfo { public final ResolvedJavaType context; - public AssumptionInlineInfo(Invoke invoke, double weight, int level, ResolvedJavaType context, ResolvedJavaMethod concrete) { - super(invoke, weight, level, concrete); + public AssumptionInlineInfo(Invoke invoke, double weight, ResolvedJavaType context, ResolvedJavaMethod concrete) { + super(invoke, weight, concrete); this.context = context; } @Override - public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) { + public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) { if (Debug.isLogEnabled()) { String targetName = MetaUtil.format("%H.%n(%p):%r", invoke.methodCallTarget().targetMethod()); String concreteName = MetaUtil.format("%H.%n(%p):%r", concrete); Debug.log("recording concrete method assumption: %s on receiver type %s -> %s", targetName, context, concreteName); } - callback.recordConcreteMethodAssumption(invoke.methodCallTarget().targetMethod(), context, concrete); + assumptions.recordConcreteMethod(invoke.methodCallTarget().targetMethod(), context, concrete); - super.inline(graph, runtime, callback); + super.inline(graph, runtime, callback, assumptions); } @Override public String toString() { return "assumption " + MetaUtil.format("%H.%n(%p):%r", concrete); } - - @Override - public boolean canDeopt() { - return true; - } } /** * Determines if inlining is possible at the given invoke node. * @param invoke the invoke that should be inlined - * @param level the number of nested inlinings that lead to this invoke, or 0 if the invoke was part of the initial graph * @param runtime a GraalRuntime instance used to determine of the invoke can be inlined and/or should be intrinsified - * @param callback a callback that is used to determine the weight of a specific inlining + * @param inliningPolicy used to determine the weight of a specific inlining * @return an instance of InlineInfo, or null if no inlining is possible at the given invoke */ - public static InlineInfo getInlineInfo(Invoke invoke, int level, GraalCodeCacheProvider runtime, Assumptions assumptions, InliningCallback callback, OptimisticOptimizations optimisticOpts) { - if (!(invoke.callTarget() instanceof MethodCallTargetNode)) { - // The invoke has already been lowered , or has been created as a low-level node. We have no method information. + public static InlineInfo getInlineInfo(Invoke invoke, GraalCodeCacheProvider runtime, Assumptions assumptions, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts) { + if (!checkInvokeConditions(invoke)) { return null; } ResolvedJavaMethod caller = getCaller(invoke); MethodCallTargetNode callTarget = invoke.methodCallTarget(); ResolvedJavaMethod targetMethod = callTarget.targetMethod(); - if (targetMethod == null) { - return null; - } - if (!checkInvokeConditions(invoke)) { - return null; - } if (callTarget.invokeKind() == InvokeKind.Special || targetMethod.canBeStaticallyBound()) { - if (checkTargetConditions(invoke, targetMethod, optimisticOpts, runtime)) { - double weight = callback == null ? 0 : callback.inliningWeight(caller, targetMethod, invoke); - return new ExactInlineInfo(invoke, weight, level, targetMethod); + if (!checkTargetConditions(invoke, targetMethod, optimisticOpts, runtime)) { + return null; } - return null; + double weight = inliningPolicy.inliningWeight(caller, targetMethod, invoke); + return new ExactInlineInfo(invoke, weight, targetMethod); } ObjectStamp receiverStamp = callTarget.receiver().objectStamp(); ResolvedJavaType receiverType = receiverStamp.type(); if (receiverStamp.isExactType()) { assert receiverType.isSubtypeOf(targetMethod.getDeclaringClass()) : receiverType + " subtype of " + targetMethod.getDeclaringClass() + " for " + targetMethod; ResolvedJavaMethod resolved = receiverType.resolveMethod(targetMethod); - if (checkTargetConditions(invoke, resolved, optimisticOpts, runtime)) { - double weight = callback == null ? 0 : callback.inliningWeight(caller, resolved, invoke); - return new ExactInlineInfo(invoke, weight, level, resolved); + if (!checkTargetConditions(invoke, resolved, optimisticOpts, runtime)) { + return null; } - return null; + double weight = inliningPolicy.inliningWeight(caller, resolved, invoke); + return new ExactInlineInfo(invoke, weight, resolved); } ResolvedJavaType holder = targetMethod.getDeclaringClass(); @@ -626,101 +637,86 @@ } } // TODO (thomaswue) fix this - if (assumptions != null) { + if (assumptions.useOptimisticAssumptions()) { ResolvedJavaMethod concrete = holder.findUniqueConcreteMethod(targetMethod); if (concrete != null) { - if (checkTargetConditions(invoke, concrete, optimisticOpts, runtime)) { - double weight = callback == null ? 0 : callback.inliningWeight(caller, concrete, invoke); - return new AssumptionInlineInfo(invoke, weight, level, holder, concrete); + if (!checkTargetConditions(invoke, concrete, optimisticOpts, runtime)) { + return null; } - return null; + double weight = inliningPolicy.inliningWeight(caller, concrete, invoke); + return new AssumptionInlineInfo(invoke, weight, holder, concrete); } } // type check based inlining - return getTypeCheckedInlineInfo(invoke, level, callback, caller, targetMethod, optimisticOpts, runtime); + return getTypeCheckedInlineInfo(invoke, inliningPolicy, caller, targetMethod, optimisticOpts, runtime); } - private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, int level, InliningCallback callback, ResolvedJavaMethod caller, ResolvedJavaMethod targetMethod, OptimisticOptimizations optimisticOpts, GraalCodeCacheProvider runtime) { + private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, InliningPolicy inliningPolicy, ResolvedJavaMethod caller, + ResolvedJavaMethod targetMethod, OptimisticOptimizations optimisticOpts, GraalCodeCacheProvider runtime) { ProfilingInfo profilingInfo = caller.getProfilingInfo(); JavaTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci()); - if (typeProfile != null) { - ProfiledType[] ptypes = typeProfile.getTypes(); - - if (ptypes != null && ptypes.length > 0) { - double notRecordedTypeProbability = typeProfile.getNotRecordedProbability(); - if (ptypes.length == 1 && notRecordedTypeProbability == 0) { - if (optimisticOpts.inlineMonomorphicCalls()) { - ResolvedJavaType type = ptypes[0].getType(); - ResolvedJavaMethod concrete = type.resolveMethod(targetMethod); - if (checkTargetConditions(invoke, concrete, optimisticOpts, runtime)) { - double weight = callback == null ? 0 : callback.inliningWeight(caller, concrete, invoke); - return new TypeGuardInlineInfo(invoke, weight, level, concrete, type); - } - - Debug.log("not inlining %s because method can't be inlined", methodName(targetMethod, invoke)); - return null; - } else { - Debug.log("not inlining %s because GraalOptions.InlineMonomorphicCalls == false", methodName(targetMethod, invoke)); - return null; - } - } else { - invoke.setMegamorphic(true); - if (optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0 || optimisticOpts.inlineMegamorphicCalls() && notRecordedTypeProbability > 0) { - // TODO (chaeubl) inlining of multiple methods should work differently - // 1. check which methods can be inlined - // 2. for those methods, use weight and probability to compute which of them should be inlined - // 3. do the inlining - // a) all seen methods can be inlined -> do so and guard with deopt - // b) some methods can be inlined -> inline them and fall back to invocation if violated - // TODO (chaeubl) sort types by probability + if (typeProfile == null) { + return logNotInlinedMethodAndReturnNull("not inlining %s because no type profile exists", methodName(targetMethod, invoke)); + } - // determine concrete methods and map type to specific method - ArrayList concreteMethods = new ArrayList<>(); - int[] typesToConcretes = new int[ptypes.length]; - for (int i = 0; i < ptypes.length; i++) { - ResolvedJavaMethod concrete = ptypes[i].getType().resolveMethod(targetMethod); - - int index = concreteMethods.indexOf(concrete); - if (index < 0) { - index = concreteMethods.size(); - concreteMethods.add(concrete); - } - typesToConcretes[i] = index; - } + ProfiledType[] ptypes = typeProfile.getTypes(); + if (ptypes == null || ptypes.length <= 0) { + return logNotInlinedMethodAndReturnNull("not inlining %s because no types/probabilities were recorded", methodName(targetMethod, invoke)); + } - double totalWeight = 0; - boolean canInline = true; - for (ResolvedJavaMethod concrete: concreteMethods) { - if (!checkTargetConditions(invoke, concrete, optimisticOpts, runtime)) { - canInline = false; - break; - } - totalWeight += callback == null ? 0 : callback.inliningWeight(caller, concrete, invoke); - } - - if (canInline) { - return new MultiTypeGuardInlineInfo(invoke, totalWeight, level, concreteMethods, ptypes, typesToConcretes, notRecordedTypeProbability); - } else { - Debug.log("not inlining %s because it is a polymorphic method call and at least one invoked method cannot be inlined", methodName(targetMethod, invoke)); - return null; - } - } else { - if (!optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0) { - Debug.log("not inlining %s because GraalOptions.InlinePolymorphicCalls == false", methodName(targetMethod, invoke)); - } else { - Debug.log("not inlining %s because GraalOptions.InlineMegamorphicCalls == false", methodName(targetMethod, invoke)); - } - return null; - } - } + double notRecordedTypeProbability = typeProfile.getNotRecordedProbability(); + if (ptypes.length == 1 && notRecordedTypeProbability == 0) { + if (!optimisticOpts.inlineMonomorphicCalls()) { + return logNotInlinedMethodAndReturnNull("not inlining %s because inlining monomorphic calls is disabled", methodName(targetMethod, invoke)); } - Debug.log("not inlining %s because no types/probabilities were recorded", methodName(targetMethod, invoke)); - return null; + ResolvedJavaType type = ptypes[0].getType(); + ResolvedJavaMethod concrete = type.resolveMethod(targetMethod); + if (!checkTargetConditions(invoke, concrete, optimisticOpts, runtime)) { + return null; + } + double weight = inliningPolicy.inliningWeight(caller, concrete, invoke); + return new TypeGuardInlineInfo(invoke, weight, concrete, type); } else { - Debug.log("not inlining %s because no type profile exists", methodName(targetMethod, invoke)); - return null; + invoke.setMegamorphic(true); + + if (!optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0) { + return logNotInlinedMethodAndReturnNull("not inlining %s because inlining polymorphic calls is disabled", methodName(targetMethod, invoke)); + } + if (!optimisticOpts.inlineMegamorphicCalls() && notRecordedTypeProbability > 0) { + return logNotInlinedMethodAndReturnNull("not inlining %s because inlining megamorphic calls is disabled", methodName(targetMethod, invoke)); + } + + // TODO (chaeubl) inlining of multiple methods should work differently + // 1. check which methods can be inlined + // 2. for those methods, use weight and probability to compute which of them should be inlined + // 3. do the inlining + // a) all seen methods can be inlined -> do so and guard with deopt + // b) some methods can be inlined -> inline them and fall back to invocation if violated + + // determine concrete methods and map type to specific method + ArrayList concreteMethods = new ArrayList<>(); + int[] typesToConcretes = new int[ptypes.length]; + for (int i = 0; i < ptypes.length; i++) { + ResolvedJavaMethod concrete = ptypes[i].getType().resolveMethod(targetMethod); + + int index = concreteMethods.indexOf(concrete); + if (index < 0) { + index = concreteMethods.size(); + concreteMethods.add(concrete); + } + typesToConcretes[i] = index; + } + + double totalWeight = 0; + for (ResolvedJavaMethod concrete: concreteMethods) { + if (!checkTargetConditions(invoke, concrete, optimisticOpts, runtime)) { + return logNotInlinedMethodAndReturnNull("not inlining %s because it is a polymorphic method call and at least one invoked method cannot be inlined", methodName(targetMethod, invoke)); + } + totalWeight += inliningPolicy.inliningWeight(caller, concrete, invoke); + } + return new MultiTypeGuardInlineInfo(invoke, totalWeight, concreteMethods, ptypes, typesToConcretes, notRecordedTypeProbability); } } @@ -734,53 +730,51 @@ } private static boolean checkInvokeConditions(Invoke invoke) { - if (invoke.stateAfter() == null) { - Debug.log("not inlining %s because the invoke has no after state", methodName(invoke.methodCallTarget().targetMethod(), invoke)); - return false; + if (!(invoke.callTarget() instanceof MethodCallTargetNode)) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because the invoke has already been lowered, or has been created as a low-level node", invoke.callTarget() == null ? "callTarget=null" : invoke.callTarget().targetName()); + } else if (invoke.methodCallTarget().targetMethod() == null) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because target method is null", invoke.toString()); + } else if (invoke.stateAfter() == null) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because the invoke has no after state", methodName(invoke.methodCallTarget().targetMethod(), invoke)); + } else if (invoke.predecessor() == null || !invoke.node().isAlive()) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because the invoke is dead code", methodName(invoke.methodCallTarget().targetMethod(), invoke)); + } else if (!invoke.useForInlining()) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because invoke is marked to be not used for inlining", methodName(invoke.methodCallTarget().targetMethod(), invoke)); + } else { + return true; } - if (invoke.predecessor() == null) { - Debug.log("not inlining %s because the invoke is dead code", methodName(invoke.methodCallTarget().targetMethod(), invoke)); - return false; - } - if (!invoke.useForInlining()) { - Debug.log("not inlining %s because invoke is marked to be not used for inlining", methodName(invoke.methodCallTarget().targetMethod(), invoke)); - return false; - } - return true; } private static boolean checkTargetConditions(Invoke invoke, ResolvedJavaMethod method, OptimisticOptimizations optimisticOpts, GraalCodeCacheProvider runtime) { if (method == null) { - Debug.log("not inlining because method is not resolved"); - return false; - } - if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(invoke, method, runtime))) { - Debug.log("not inlining %s because it is a non-intrinsic native method", methodName(method, invoke)); - return false; - } - if (Modifier.isAbstract(method.getModifiers())) { - Debug.log("not inlining %s because it is an abstract method", methodName(method, invoke)); - return false; - } - if (!method.getDeclaringClass().isInitialized()) { - Debug.log("not inlining %s because of non-initialized class", methodName(method, invoke)); - return false; + return logNotInlinedMethodAndReturnFalse("not inlining because method is not resolved"); + } else if (Modifier.isNative(method.getModifiers()) && (!GraalOptions.Intrinsify || !InliningUtil.canIntrinsify(invoke, method, runtime))) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because it is a non-intrinsic native method", methodName(method, invoke)); + } else if (Modifier.isAbstract(method.getModifiers())) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because it is an abstract method", methodName(method, invoke)); + } else if (!method.getDeclaringClass().isInitialized()) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because of non-initialized class", methodName(method, invoke)); + } else if (!method.canBeInlined()) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because it is marked non-inlinable", methodName(method, invoke)); + } else if (computeInliningLevel(invoke) > GraalOptions.MaximumInlineLevel) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because it excees the maximum inlining depth", methodName(method, invoke)); + } else if (computeRecursiveInliningLevel(invoke.stateAfter(), method) > GraalOptions.MaximumRecursiveInlining) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(method, invoke)); + } else if (new OptimisticOptimizations(method).lessOptimisticThan(optimisticOpts)) { + return logNotInlinedMethodAndReturnFalse("not inlining %s because callee uses less optimistic optimizations than caller", methodName(method, invoke)); + } else { + return true; } - if (!method.canBeInlined()) { - Debug.log("not inlining %s because it is marked non-inlinable", methodName(method, invoke)); - return false; - } - if (computeRecursiveInliningLevel(invoke.stateAfter(), method) > GraalOptions.MaximumRecursiveInlining) { - Debug.log("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(method, invoke)); - return false; + } + + private static int computeInliningLevel(Invoke invoke) { + int count = -1; + FrameState curState = invoke.stateAfter(); + while (curState != null) { + count++; + curState = curState.outerFrameState(); } - OptimisticOptimizations calleeOpts = new OptimisticOptimizations(method); - if (calleeOpts.lessOptimisticThan(optimisticOpts)) { - Debug.log("not inlining %s because callee uses less optimistic optimizations than caller", methodName(method, invoke)); - return false; - } - - return true; + return count; } private static int computeRecursiveInliningLevel(FrameState state, ResolvedJavaMethod method) { diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Thu Nov 22 13:30:14 2012 +0100 @@ -43,12 +43,12 @@ static boolean InlineMonomorphicCalls = true; static boolean InlinePolymorphicCalls = true; static boolean InlineMegamorphicCalls = ____; - public static int InliningPolicy = 4; + public static int InliningPolicy = 0; + public static int InliningDecision = 4; public static int WeightComputationPolicy = 2; public static int MaximumTrivialSize = 10; public static int MaximumInlineLevel = 30; public static int MaximumDesiredSize = 3000; - public static boolean AlwaysInlineTrivialMethods = ____; public static int MaximumRecursiveInlining = 1; public static int SmallCompiledCodeSize = 2200; public static boolean LimitInlinedProbability = ____; diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java --- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Thu Nov 22 13:30:14 2012 +0100 @@ -32,7 +32,7 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.snippets.Snippet.InliningPolicy; +import com.oracle.graal.snippets.Snippet.SnippetInliningPolicy; /** * Tests for the {@link Word} type. @@ -43,10 +43,10 @@ public WordTest() { TargetDescription target = Graal.getRequiredCapability(GraalCompiler.class).target; - installer = new SnippetInstaller(runtime, target); + installer = new SnippetInstaller(runtime, target, new Assumptions(false)); } - private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); + private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); @Override protected StructuredGraph parse(Method m) { @@ -114,9 +114,9 @@ @Test public void test_fromObject() { - inliningPolicy.set(new InliningPolicy() { + inliningPolicy.set(new SnippetInliningPolicy() { public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { - return InliningPolicy.Default.shouldInline(method, caller) && !method.getName().equals("hashCode"); + return SnippetInliningPolicy.Default.shouldInline(method, caller) && !method.getName().equals("hashCode"); } }); test("fromToObject", "object1", "object2"); diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Thu Nov 22 13:30:14 2012 +0100 @@ -26,6 +26,7 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -54,8 +55,8 @@ */ public abstract class InstanceOfSnippetsTemplates extends AbstractTemplates { - public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Class snippetsClass) { - super(runtime, snippetsClass); + public InstanceOfSnippetsTemplates(MetaAccessProvider runtime, Assumptions assumptions, Class snippetsClass) { + super(runtime, assumptions, snippetsClass); } /** @@ -91,7 +92,7 @@ replacer.replaceUsingInstantiation(); } else { KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool); - SnippetTemplate template = cache.get(keyAndArguments.key); + SnippetTemplate template = cache.get(keyAndArguments.key, assumptions); template.instantiate(runtime, instanceOf, replacer, tool.lastFixedNode(), keyAndArguments.arguments); } } diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Thu Nov 22 13:30:14 2012 +0100 @@ -45,14 +45,14 @@ /** * Specifies the class defining the inlining policy for this snippet. - * A {@linkplain InliningPolicy#Default default} policy is used if none is supplied. + * A {@linkplain SnippetInliningPolicy#Default default} policy is used if none is supplied. */ - Class inlining() default InliningPolicy.class; + Class inlining() default SnippetInliningPolicy.class; /** * Guides inlining decisions used when installing a snippet. */ - public interface InliningPolicy { + public interface SnippetInliningPolicy { /** * Determines if {@code method} should be inlined into {@code caller}. */ @@ -68,7 +68,7 @@ *
  • constructors of {@link Throwable} classes
  • * */ - InliningPolicy Default = new InliningPolicy() { + SnippetInliningPolicy Default = new SnippetInliningPolicy() { public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { if (Modifier.isNative(method.getModifiers())) { return false; diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Thu Nov 22 13:30:14 2012 +0100 @@ -37,7 +37,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; -import com.oracle.graal.snippets.Snippet.InliningPolicy; +import com.oracle.graal.snippets.Snippet.SnippetInliningPolicy; /** * Utility for snippet {@linkplain #install(Class) installation}. @@ -46,6 +46,7 @@ private final MetaAccessProvider runtime; private final TargetDescription target; + private final Assumptions assumptions; private final BoxingMethodPool pool; /** @@ -56,9 +57,10 @@ */ private final Map graphCache; - public SnippetInstaller(MetaAccessProvider runtime, TargetDescription target) { + public SnippetInstaller(MetaAccessProvider runtime, TargetDescription target, Assumptions assumptions) { this.runtime = runtime; this.target = target; + this.assumptions = assumptions; this.pool = new BoxingMethodPool(runtime); this.graphCache = new HashMap<>(); } @@ -120,14 +122,14 @@ } } - private static InliningPolicy inliningPolicy(ResolvedJavaMethod method) { - Class policyClass = InliningPolicy.class; + private static SnippetInliningPolicy inliningPolicy(ResolvedJavaMethod method) { + Class policyClass = SnippetInliningPolicy.class; Snippet snippet = method.getAnnotation(Snippet.class); if (snippet != null) { policyClass = snippet.inlining(); } - if (policyClass == InliningPolicy.class) { - return InliningPolicy.Default; + if (policyClass == SnippetInliningPolicy.class) { + return SnippetInliningPolicy.Default; } try { return policyClass.getConstructor().newInstance(); @@ -136,7 +138,7 @@ } } - public StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { + public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { StructuredGraph graph = parseGraph(method, policy); new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph); @@ -146,7 +148,7 @@ return graph; } - private StructuredGraph parseGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { + private StructuredGraph parseGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { StructuredGraph graph = graphCache.get(method); if (graph == null) { graph = buildGraph(method, policy == null ? inliningPolicy(method) : policy); @@ -156,7 +158,7 @@ return graph; } - private StructuredGraph buildGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { + private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { final StructuredGraph graph = new StructuredGraph(method); return Debug.scope("BuildSnippetGraph", new Object[] {method, graph}, new Callable() { @Override @@ -180,7 +182,7 @@ Debug.dump(graph, "after inlining %s", callee); if (GraalOptions.OptCanonicalizer) { new WordTypeRewriterPhase(target.wordKind, runtime.lookupJavaType(target.wordKind.toJavaClass())).apply(graph); - new CanonicalizerPhase(target, runtime, null).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } } } @@ -191,7 +193,7 @@ new DeadCodeEliminationPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, null).apply(graph); + new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) { diff -r 0d7dfa5b79e8 -r 8d16b9b2c51e graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Thu Nov 15 15:10:41 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Thu Nov 22 13:30:14 2012 +0100 @@ -27,6 +27,7 @@ import java.util.Map.Entry; import java.util.concurrent.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; @@ -162,13 +163,13 @@ /** * Gets a template for a given key, creating it first if necessary. */ - public SnippetTemplate get(final SnippetTemplate.Key key) { + public SnippetTemplate get(final SnippetTemplate.Key key, final Assumptions assumptions) { SnippetTemplate template = templates.get(key); if (template == null) { template = Debug.scope("SnippetSpecialization", key.method, new Callable() { @Override public SnippetTemplate call() throws Exception { - return new SnippetTemplate(runtime, key); + return new SnippetTemplate(runtime, key, assumptions); } }); //System.out.println(key + " -> " + template); @@ -181,9 +182,12 @@ public abstract static class AbstractTemplates { protected final Cache cache; protected final MetaAccessProvider runtime; + protected final Assumptions assumptions; protected Class snippetsClass; - public AbstractTemplates(MetaAccessProvider runtime, Class snippetsClass) { + + public AbstractTemplates(MetaAccessProvider runtime, Assumptions assumptions, Class snippetsClass) { this.runtime = runtime; + this.assumptions = assumptions; this.snippetsClass = snippetsClass; this.cache = new Cache(runtime); } @@ -214,7 +218,7 @@ /** * Creates a snippet template. */ - public SnippetTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key) { + public SnippetTemplate(MetaAccessProvider runtime, SnippetTemplate.Key key, Assumptions assumptions) { ResolvedJavaMethod method = key.method; assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + method; Signature signature = method.getSignature(); @@ -259,7 +263,7 @@ // Do deferred intrinsification of node intrinsics new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy); - new CanonicalizerPhase(null, runtime, null, 0, null).apply(snippetCopy); + new CanonicalizerPhase(null, runtime, assumptions, 0, null).apply(snippetCopy); } // Gather the template parameters @@ -311,8 +315,8 @@ if (loopBegin != null) { LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin); int mark = snippetCopy.getMark(); - LoopTransformations.fullUnroll(loop, runtime); - new CanonicalizerPhase(null, runtime, null, mark, null).apply(snippetCopy); + LoopTransformations.fullUnroll(loop, runtime, null); + new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(snippetCopy); } FixedNode explodeLoopNext = explodeLoop.next(); explodeLoop.clearSuccessors();