# HG changeset patch # User Lukas Stadler # Date 1389280709 -3600 # Node ID f4f0a8a01ce0b4e8bcb4fa2c3fa7618af0a9fcc7 # Parent 9267de45985bacb7efa6aa87dea67ae5fe4e0b99 remove PhasePlan diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Thu Jan 09 16:18:29 2014 +0100 @@ -38,12 +38,10 @@ import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.ptx.*; -import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.ptx.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.ptx.*; @@ -73,10 +71,8 @@ Debug.dump(graph, "Graph"); Backend ptxBackend = getBackend(); TargetDescription target = ptxBackend.getTarget(); - PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(getMetaAccess(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase()); + PhaseSuite graphBuilderSuite = getDefaultGraphBuilderSuite().copy(); + graphBuilderSuite.appendPhase(new PTXPhase()); new PTXPhase().apply(graph); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); /* @@ -89,8 +85,8 @@ * GPU fallback to CPU in cases of ECC failure on kernel invocation. */ Suites suites = Suites.createDefaultSuites(); - ExternalCompilationResult result = compileGraph(graph, cc, graph.method(), getProviders(), ptxBackend, target, null, phasePlan, OptimisticOptimizations.NONE, getProfilingInfo(graph), - new SpeculationLog(), suites, true, new ExternalCompilationResult(), CompilationResultBuilderFactory.Default); + ExternalCompilationResult result = compileGraph(graph, cc, graph.method(), getProviders(), ptxBackend, target, null, graphBuilderSuite, OptimisticOptimizations.NONE, + getProfilingInfo(graph), new SpeculationLog(), suites, true, new ExternalCompilationResult(), CompilationResultBuilderFactory.Default); ResolvedJavaMethod method = graph.method(); diff -r 9267de45985b -r f4f0a8a01ce0 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 Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -306,7 +306,7 @@ private void processMethod(final String snippet) { graph = parse(snippet); Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context); } @@ -319,7 +319,7 @@ graph = parse(snippet); Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); if (loopPeeling) { diff -r 9267de45985b -r f4f0a8a01ce0 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 Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -81,7 +81,7 @@ private void test(final String snippet) { try (Scope s = Debug.scope("DegeneratedLoopsTest", new DebugDumpScope(snippet))) { StructuredGraph graph = parse(snippet); - HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); Debug.dump(graph, "Graph"); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -66,8 +66,8 @@ StructuredGraph graph = new StructuredGraph(javaMethod); GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(); - new GraphBuilderPhase(getMetaAccess(), conf, OptimisticOptimizations.ALL).apply(graph); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + new GraphBuilderPhase.Instance(getMetaAccess(), conf, OptimisticOptimizations.ALL).apply(graph); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); return graph; diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -51,7 +51,6 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; @@ -549,12 +548,9 @@ TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s ...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature())); } long start = System.currentTimeMillis(); - PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(getMetaAccess(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - final CompilationResult compResult = compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, - getProfilingInfo(graph), new SpeculationLog(), getSuites(), true, new CompilationResult(), CompilationResultBuilderFactory.Default); + final CompilationResult compResult = compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), + OptimisticOptimizations.ALL, getProfilingInfo(graph), new SpeculationLog(), getSuites(), true, new CompilationResult(), CompilationResultBuilderFactory.Default); if (printCompilation) { TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); } @@ -617,20 +613,24 @@ assert m.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + m; ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(m); StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(getMetaAccess(), conf, OptimisticOptimizations.ALL).apply(graph); + new GraphBuilderPhase.Instance(getMetaAccess(), conf, OptimisticOptimizations.ALL).apply(graph); return graph; } - protected PhasePlan getDefaultPhasePlan() { - return getDefaultPhasePlan(false); + protected PhaseSuite getDefaultGraphBuilderSuite() { + // defensive copying + return backend.getSuites().getDefaultGraphBuilderSuite().copy(); } - protected PhasePlan getDefaultPhasePlan(boolean eagerInfopointMode) { - PhasePlan plan = new PhasePlan(); + protected PhaseSuite getEagerGraphBuilderSuite() { GraphBuilderConfiguration gbConf = GraphBuilderConfiguration.getEagerDefault(); - gbConf.setEagerInfopointMode(eagerInfopointMode); - plan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(getMetaAccess(), gbConf, OptimisticOptimizations.ALL)); - return plan; + gbConf.setEagerInfopointMode(true); + + PhaseSuite suite = getDefaultGraphBuilderSuite().copy(); + ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); + iterator.remove(); + iterator.add(new GraphBuilderPhase(gbConf)); + return suite; } protected Replacements getReplacements() { diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -60,8 +60,8 @@ final Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - final CompilationResult cr = compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL, - getProfilingInfo(graph), new SpeculationLog(), getSuites(), true, new CompilationResult(), CompilationResultBuilderFactory.Default); + final CompilationResult cr = compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), + OptimisticOptimizations.ALL, getProfilingInfo(graph), new SpeculationLog(), getSuites(), true, new CompilationResult(), CompilationResultBuilderFactory.Default); for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); if (sp instanceof Call) { @@ -82,7 +82,7 @@ } assertTrue(graphLineSPs > 0); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - final CompilationResult cr = compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultPhasePlan(true), OptimisticOptimizations.ALL, + final CompilationResult cr = compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getEagerGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graph), new SpeculationLog(), getSuites(), true, new CompilationResult(), CompilationResultBuilderFactory.Default); int lineSPs = 0; for (Infopoint sp : cr.getInfopoints()) { diff -r 9267de45985b -r f4f0a8a01ce0 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 Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -66,7 +66,7 @@ hints.put(invoke, 1000d); } Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); diff -r 9267de45985b -r f4f0a8a01ce0 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 Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -77,7 +77,7 @@ } Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -89,9 +89,8 @@ private StructuredGraph getGraph(String snippet) { Method method = getMethod(snippet); StructuredGraph graph = parse(method); - PhasePlan phasePlan = getDefaultPhasePlan(); Assumptions assumptions = new Assumptions(true); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, phasePlan, OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new CanonicalizerPhase(true).apply(graph, context); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -587,7 +587,7 @@ try (Scope d = Debug.scope("FloatingReadTest", graph)) { try (OverrideScope s = OptionValue.override(OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS)) { Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); canonicalizer.apply(graph, context); if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { diff -r 9267de45985b -r f4f0a8a01ce0 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 Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -94,7 +94,7 @@ hints.put(invoke, 1000d); } Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -107,13 +107,12 @@ } private RegisterStats getRegisterStats(final StructuredGraph graph) { - final PhasePlan phasePlan = getDefaultPhasePlan(); final Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); LIR lir = null; try (Scope s = Debug.scope("FrontEnd")) { - lir = GraalCompiler.emitHIR(getProviders(), getBackend().getTarget(), graph, assumptions, null, phasePlan, OptimisticOptimizations.NONE, graph.method().getProfilingInfo(), - new SpeculationLog(), getSuites()); + lir = GraalCompiler.emitHIR(getProviders(), getBackend().getTarget(), graph, assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, + graph.method().getProfilingInfo(), new SpeculationLog(), getSuites()); } catch (Throwable e) { throw Debug.handle(e); } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java Thu Jan 09 16:18:29 2014 +0100 @@ -146,9 +146,9 @@ ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(getMethod(snippet)); graph = new StructuredGraph(method); try (Scope s = Debug.scope(getClass().getSimpleName(), graph, method, getCodeCache())) { - new GraphBuilderPhase(getMetaAccess(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + new GraphBuilderPhase.Instance(getMetaAccess(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); Assumptions assumptions = new Assumptions(false); - context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase(true).apply(graph, context); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -41,7 +41,7 @@ protected void processMethod(final String snippet) { graph = parse(snippet); Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new EarlyReadEliminationPhase(new CanonicalizerPhase(true)).apply(graph, context); } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -85,7 +85,7 @@ private void processMethod(final String snippet) { graph = parse(snippet); - HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new IterativeInliningPhase(new CanonicalizerPhase(true)).apply(graph, context); } } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -243,7 +243,7 @@ protected void processMethod(final String snippet) { graph = parse(snippet); Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new PartialEscapePhase(false, true, new CanonicalizerPhase(true)).apply(graph, context); } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -232,9 +232,9 @@ try (Scope s = Debug.scope("InliningTest", new DebugDumpScope(snippet))) { Method method = getMethod(snippet); StructuredGraph graph = eagerInfopointMode ? parseDebug(method) : parse(method); - PhasePlan phasePlan = getDefaultPhasePlan(eagerInfopointMode); + PhaseSuite graphBuilderSuite = eagerInfopointMode ? getEagerGraphBuilderSuite() : getDefaultGraphBuilderSuite(); Assumptions assumptions = new Assumptions(true); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, phasePlan, OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, graphBuilderSuite, OptimisticOptimizations.ALL); Debug.dump(graph, "Graph"); new CanonicalizerPhase(true).apply(graph, context); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); diff -r 9267de45985b -r f4f0a8a01ce0 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 Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Jan 09 16:18:29 2014 +0100 @@ -47,7 +47,6 @@ import com.oracle.graal.nodes.util.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; @@ -137,13 +136,13 @@ * @return the result of the compilation */ public static T compileGraph(StructuredGraph graph, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, - TargetDescription target, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, SpeculationLog speculationLog, Suites suites, - boolean withScope, T compilationResult, CompilationResultBuilderFactory factory) { + TargetDescription target, GraphCache cache, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, + SpeculationLog speculationLog, Suites suites, boolean withScope, T compilationResult, CompilationResultBuilderFactory factory) { try (Scope s0 = withScope ? Debug.scope("GraalCompiler", graph, providers.getCodeCache()) : null) { Assumptions assumptions = new Assumptions(OptAssumptions.getValue()); LIR lir = null; try (Scope s = Debug.scope("FrontEnd"); TimerCloseable a = FrontEnd.start()) { - lir = emitHIR(providers, target, graph, assumptions, cache, plan, optimisticOpts, profilingInfo, speculationLog, suites); + lir = emitHIR(providers, target, graph, assumptions, cache, graphBuilderSuite, optimisticOpts, profilingInfo, speculationLog, suites); } catch (Throwable e) { throw Debug.handle(e); } @@ -189,21 +188,21 @@ /** * Builds the graph, optimizes it. */ - public static LIR emitHIR(Providers providers, TargetDescription target, StructuredGraph graph, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts, - ProfilingInfo profilingInfo, SpeculationLog speculationLog, Suites suites) { + public static LIR emitHIR(Providers providers, TargetDescription target, StructuredGraph graph, Assumptions assumptions, GraphCache cache, PhaseSuite graphBuilderSuite, + OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, SpeculationLog speculationLog, Suites suites) { if (speculationLog != null) { speculationLog.snapshot(); } + HighTierContext highTierContext = new HighTierContext(providers, assumptions, cache, graphBuilderSuite, optimisticOpts); if (graph.start().next() == null) { - plan.runPhases(PhasePosition.AFTER_PARSING, graph); + graphBuilderSuite.apply(graph, highTierContext); new DeadCodeEliminationPhase().apply(graph); } else { Debug.dump(graph, "initial state"); } - HighTierContext highTierContext = new HighTierContext(providers, assumptions, cache, plan, optimisticOpts); suites.getHighTier().apply(graph, highTierContext); graph.maybeCompress(); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILCompilationResult.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILCompilationResult.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILCompilationResult.java Thu Jan 09 16:18:29 2014 +0100 @@ -45,7 +45,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.runtime.*; @@ -93,7 +92,7 @@ public static HSAILCompilationResult getHSAILCompilationResult(ResolvedJavaMethod javaMethod) { HotSpotMetaAccessProvider metaAccess = backend.getProviders().getMetaAccess(); StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); return getHSAILCompilationResult(graph); } @@ -142,8 +141,7 @@ HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) providers.getMetaAccess(); ResolvedJavaMethod rm = metaAccess.lookupJavaMethod(acceptMethod); StructuredGraph graph = new StructuredGraph(rm); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(providers.getMetaAccess(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); - graphBuilderPhase.apply(graph); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL).apply(graph); NodeIterable nin = graph.getNodes(); ResolvedJavaMethod lambdaMethod = null; for (Node n : nin) { @@ -167,15 +165,13 @@ Debug.dump(graph, "Graph"); Providers providers = backend.getProviders(); TargetDescription target = providers.getCodeCache().getTarget(); - PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(providers.getMetaAccess(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, new HSAILPhase()); + PhaseSuite graphBuilderSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy(); + graphBuilderSuite.appendPhase(new HSAILPhase()); new HSAILPhase().apply(graph); CallingConvention cc = getHSAILCallingConvention(Type.JavaCallee, target, graph.method(), false); SuitesProvider suitesProvider = backend.getSuites(); try { - HSAILCompilationResult compResult = compileGraph(graph, cc, graph.method(), providers, backend, target, null, phasePlan, OptimisticOptimizations.NONE, getProfilingInfo(graph), + HSAILCompilationResult compResult = compileGraph(graph, cc, graph.method(), providers, backend, target, null, graphBuilderSuite, OptimisticOptimizations.NONE, getProfilingInfo(graph), new SpeculationLog(), suitesProvider.getDefaultSuites(), true, new HSAILCompilationResult(), CompilationResultBuilderFactory.Default); if ((validDevice) && (compResult.getTargetCode() != null)) { long kernel = toGPU.generateKernel(compResult.getTargetCode(), graph.method().getName()); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -36,14 +36,12 @@ import com.oracle.graal.compiler.test.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.options.*; import com.oracle.graal.options.OptionValue.OverrideScope; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.runtime.*; @@ -202,14 +200,11 @@ ResolvedJavaMethod method = graph.method(); try (OverrideScope s = OptionValue.override(ImmutableCode, compileAOT)) { - PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(getMetaAccess(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); // create suites everytime, as we modify options for the compiler final Suites suitesLocal = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().createSuites(); - final CompilationResult compResult = compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, - getProfilingInfo(graph), new SpeculationLog(), suitesLocal, true, new CompilationResult(), CompilationResultBuilderFactory.Default); + final CompilationResult compResult = compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultGraphBuilderSuite(), + OptimisticOptimizations.ALL, getProfilingInfo(graph), new SpeculationLog(), suitesLocal, true, new CompilationResult(), CompilationResultBuilderFactory.Default); addMethod(method, compResult); } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -247,7 +247,7 @@ private void test(final String snippet, final int expectedBarriers) throws Exception, SecurityException { try (Scope s = Debug.scope("WriteBarrierAdditionTest", new DebugDumpScope(snippet))) { StructuredGraph graph = parse(snippet); - HighTierContext highContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext highContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); MidTierContext midContext = new MidTierContext(getProviders(), new Assumptions(false), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo()); new InliningPhase(new InliningPhase.InlineEverythingPolicy(), new CanonicalizerPhase(true)).apply(graph, highContext); new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -613,7 +613,7 @@ private void test(final String snippet, final int expectedBarriers, final int... removedBarrierIndices) { try (Scope d = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) { final StructuredGraph graph = parse(snippet); - HighTierContext highTierContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + HighTierContext highTierContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); MidTierContext midTierContext = new MidTierContext(getProviders(), new Assumptions(false), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo()); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu Jan 09 16:18:29 2014 +0100 @@ -43,14 +43,11 @@ import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.phases.*; -import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.phases.util.*; public class CompilationTask implements Runnable { @@ -118,15 +115,15 @@ return providers.getSuites().getDefaultSuites(); } - protected PhasePlan getPhasePlan(Providers providers, OptimisticOptimizations optimisticOpts) { + protected PhaseSuite getGraphBuilderSuite(HotSpotProviders providers) { + PhaseSuite suite = providers.getSuites().getDefaultGraphBuilderSuite(); + boolean osrCompilation = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; - PhasePlan phasePlan = new PhasePlan(); - MetaAccessProvider metaAccess = providers.getMetaAccess(); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(metaAccess, GraphBuilderConfiguration.getDefault(), optimisticOpts)); if (osrCompilation) { - phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase()); + suite = suite.copy(); + suite.appendPhase(new OnStackReplacementPhase()); } - return phasePlan; + return suite; } protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo) { @@ -185,9 +182,8 @@ Suites suites = getSuites(providers); ProfilingInfo profilingInfo = getProfilingInfo(); OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo); - PhasePlan phasePlan = getPhasePlan(providers, optimisticOpts); - result = compileGraph(graph, cc, method, providers, backend, backend.getTarget(), graphCache, phasePlan, optimisticOpts, profilingInfo, method.getSpeculationLog(), suites, true, - new CompilationResult(), CompilationResultBuilderFactory.Default); + result = compileGraph(graph, cc, method, providers, backend, backend.getTarget(), graphCache, getGraphBuilderSuite(providers), optimisticOpts, profilingInfo, + method.getSpeculationLog(), suites, true, new CompilationResult(), CompilationResultBuilderFactory.Default); } catch (Throwable e) { throw Debug.handle(e); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Thu Jan 09 16:18:29 2014 +0100 @@ -23,9 +23,10 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.phases.GraalOptions.*; - import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.phases.*; +import com.oracle.graal.java.*; +import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; /** @@ -34,10 +35,12 @@ public class HotSpotSuitesProvider implements SuitesProvider { protected final Suites defaultSuites; + protected final PhaseSuite defaultGraphBuilderSuite; private final HotSpotGraalRuntime runtime; public HotSpotSuitesProvider(HotSpotGraalRuntime runtime) { this.runtime = runtime; + this.defaultGraphBuilderSuite = createGraphBuilderSuite(); defaultSuites = createSuites(); } @@ -45,6 +48,10 @@ return defaultSuites; } + public PhaseSuite getDefaultGraphBuilderSuite() { + return defaultGraphBuilderSuite; + } + public Suites createSuites() { Suites ret = Suites.createDefaultSuites(); @@ -63,4 +70,10 @@ return ret; } + + private static PhaseSuite createGraphBuilderSuite() { + PhaseSuite suite = new PhaseSuite<>(); + suite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getDefault())); + return suite; + } } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Thu Jan 09 16:18:29 2014 +0100 @@ -38,11 +38,9 @@ import com.oracle.graal.hotspot.bridge.CompilerToVM.CodeInstallResult; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.java.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; //JaCoCo Exclude @@ -144,15 +142,12 @@ graph.replaceFixed(graph.start(), newStart); } - PhasePlan phasePlan = new PhasePlan(); - MetaAccessProvider metaAccess = providers.getMetaAccess(); CodeCacheProvider codeCache = providers.getCodeCache(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccess, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); // The stub itself needs the incoming calling convention. CallingConvention incomingCc = linkage.getIncomingCallingConvention(); - final CompilationResult compResult = compileGraph(graph, incomingCc, getInstalledCodeOwner(), providers, backend, codeCache.getTarget(), null, phasePlan, OptimisticOptimizations.ALL, - getProfilingInfo(graph), new SpeculationLog(), providers.getSuites().getDefaultSuites(), true, new CompilationResult(), CompilationResultBuilderFactory.Default); + final CompilationResult compResult = compileGraph(graph, incomingCc, getInstalledCodeOwner(), providers, backend, codeCache.getTarget(), null, + providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graph), new SpeculationLog(), + providers.getSuites().getDefaultSuites(), true, new CompilationResult(), CompilationResultBuilderFactory.Default); assert destroyedRegisters != null; try (Scope s = Debug.scope("CodeInstall")) { diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java --- a/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java Thu Jan 09 16:18:29 2014 +0100 @@ -24,7 +24,6 @@ import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.compiler.GraalCompiler.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; @@ -34,7 +33,6 @@ import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.runtime.*; @@ -45,15 +43,13 @@ Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); Providers providers = backend.getProviders(); SuitesProvider suitesProvider = backend.getSuites(); - Suites suites = suitesProvider.createSuites(); + Suites suites = suitesProvider.getDefaultSuites(); StructuredGraph graph = new StructuredGraph(method); MetaAccessProvider metaAccess = providers.getMetaAccess(); - new GraphBuilderPhase(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); - PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccess, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + PhaseSuite graphBuilderSuite = suitesProvider.getDefaultGraphBuilderSuite(); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); - compileGraph(graph, cc, method, providers, backend, providers.getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, getProfilingInfo(graph), new SpeculationLog(), suites, - true, new CompilationResult(), CompilationResultBuilderFactory.Default); + compileGraph(graph, cc, method, providers, backend, providers.getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, getProfilingInfo(graph), new SpeculationLog(), + suites, true, new CompilationResult(), CompilationResultBuilderFactory.Default); } } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Jan 09 16:18:29 2014 +0100 @@ -51,11 +51,12 @@ import com.oracle.graal.nodes.util.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; /** * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph. */ -public class GraphBuilderPhase extends Phase { +public class GraphBuilderPhase extends BasePhase { static class Options { // @formatter:off @@ -82,1557 +83,1590 @@ */ public static final int TRACELEVEL_STATE = 2; - private LineNumberTable lnt; - private int previousLineNumber; - private int currentLineNumber; - - protected StructuredGraph currentGraph; - - /** - * Head of placeholder list. - */ - protected BlockPlaceholderNode placeholders; - - private final MetaAccessProvider metaAccess; - private ConstantPool constantPool; - private ResolvedJavaMethod method; - private int entryBCI; - private ProfilingInfo profilingInfo; - - private BytecodeStream stream; // the bytecode stream - - protected FrameStateBuilder frameState; // the current execution state - private Block currentBlock; - - private ValueNode methodSynchronizedObject; - private ExceptionDispatchBlock unwindBlock; - private Block returnBlock; - - private FixedWithNextNode lastInstr; // the last instruction added - private final GraphBuilderConfiguration graphBuilderConfig; - private final OptimisticOptimizations optimisticOpts; - - /** - * Meters the number of actual bytecodes parsed. - */ - public static final DebugMetric BytecodesParsed = Debug.metric("BytecodesParsed"); - - /** - * Node that marks the begin of block during bytecode parsing. When a block is identified the - * first time as a jump target, the placeholder is created and used as the successor for the - * jump. When the block is seen the second time, a {@link MergeNode} is created to correctly - * merge the now two different predecessor states. - */ - private static class BlockPlaceholderNode extends FixedWithNextNode { - - // Cannot be explicitly declared as a Node type since it is not an input; - // would cause the !NODE_CLASS.isAssignableFrom(type) guarantee - // in NodeClass.FieldScanner.scanField() to fail. - private final Object nextPlaceholder; - - public BlockPlaceholderNode(GraphBuilderPhase builder) { - super(StampFactory.forVoid()); - nextPlaceholder = builder.placeholders; - builder.placeholders = this; - } - BlockPlaceholderNode nextPlaceholder() { - return (BlockPlaceholderNode) nextPlaceholder; - } - } - - private Block[] loopHeaders; - - /** - * Gets the current frame state being processed by this builder. - */ - protected FrameStateBuilder getCurrentFrameState() { - return frameState; - } - - /** - * Gets the graph being processed by this builder. - */ - protected StructuredGraph getGraph() { - return currentGraph; - } - - protected ResolvedJavaMethod getMethod() { - return method; - } - - public GraphBuilderPhase(MetaAccessProvider metaAccess, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { + public GraphBuilderPhase(GraphBuilderConfiguration graphBuilderConfig) { this.graphBuilderConfig = graphBuilderConfig; - this.optimisticOpts = optimisticOpts; - this.metaAccess = metaAccess; - assert metaAccess != null; - } - - @Override - protected void run(StructuredGraph graph) { - method = graph.method(); - if (graphBuilderConfig.eagerInfopointMode()) { - lnt = method.getLineNumberTable(); - previousLineNumber = -1; - } - entryBCI = graph.getEntryBCI(); - profilingInfo = method.getProfilingInfo(); - assert method.getCode() != null : "method must contain bytecodes: " + method; - this.stream = new BytecodeStream(method.getCode()); - this.constantPool = method.getConstantPool(); - unwindBlock = null; - returnBlock = null; - methodSynchronizedObject = null; - this.currentGraph = graph; - this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving()); - TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); - try { - build(); - } finally { - filter.remove(); - } } @Override - protected String getDetailedName() { - return getName() + " " + MetaUtil.format("%H.%n(%p):%r", method); - } - - private BciBlockMapping createBlockMap() { - BciBlockMapping map = new BciBlockMapping(method); - map.build(); - if (Debug.isDumpEnabled()) { - Debug.dump(map, MetaUtil.format("After block building %f %R %H.%n(%P)", method)); - } - - return map; - } - - protected void build() { - if (PrintProfilingInformation.getValue()) { - TTY.println("Profiling info for " + MetaUtil.format("%H.%n(%p)", method)); - TTY.println(MetaUtil.indent(MetaUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), " ")); - } - - Indent indent = Debug.logAndIndent("build graph for %s", method); - - // compute the block map, setup exception handlers and get the entrypoint(s) - BciBlockMapping blockMap = createBlockMap(); - loopHeaders = blockMap.loopHeaders; - - lastInstr = currentGraph.start(); - if (isSynchronized(method.getModifiers())) { - // add a monitor enter to the start block - currentGraph.start().setStateAfter(frameState.create(FrameState.BEFORE_BCI)); - methodSynchronizedObject = synchronizedObject(frameState, method); - lastInstr = genMonitorEnter(methodSynchronizedObject); - } - frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn); - ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); - - if (graphBuilderConfig.eagerInfopointMode()) { - InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START, frameState.create(0))); - lastInstr.setNext(ipn); - lastInstr = ipn; - } - - currentBlock = blockMap.startBlock; - blockMap.startBlock.entryState = frameState; - if (blockMap.startBlock.isLoopHeader) { - /* - * TODO(lstadler,gduboscq) createTarget might not be safe at this position, since it - * expects currentBlock, etc. to be set up correctly. A better solution to this problem - * of start blocks that are loop headers would be to create a dummy block in - * BciBlockMapping. - */ - appendGoto(createTarget(blockMap.startBlock, frameState)); - } else { - blockMap.startBlock.firstInstruction = lastInstr; - } - - for (Block block : blockMap.blocks) { - processBlock(block); - } - processBlock(returnBlock); - processBlock(unwindBlock); - - Debug.dump(currentGraph, "After bytecode parsing"); - - connectLoopEndToBegin(); - - // remove Placeholders - for (BlockPlaceholderNode n = placeholders; n != null; n = n.nextPlaceholder()) { - if (!n.isDeleted()) { - currentGraph.removeFixed(n); - } - } - placeholders = null; - - // remove dead FrameStates - for (Node n : currentGraph.getNodes(FrameState.class)) { - if (n.usages().isEmpty() && n.predecessor() == null) { - n.safeDelete(); - } - } - indent.outdent(); - } - - private Block unwindBlock(int bci) { - if (unwindBlock == null) { - unwindBlock = new ExceptionDispatchBlock(); - unwindBlock.startBci = -1; - unwindBlock.endBci = -1; - unwindBlock.deoptBci = bci; - unwindBlock.blockID = Integer.MAX_VALUE; - } - return unwindBlock; - } - - private Block returnBlock(int bci) { - if (returnBlock == null) { - returnBlock = new Block(); - returnBlock.startBci = bci; - returnBlock.endBci = bci; - returnBlock.blockID = Integer.MAX_VALUE; - } - return returnBlock; - } - - public BytecodeStream stream() { - return stream; - } - - public int bci() { - return stream.currentBCI(); - } - - private void loadLocal(int index, Kind kind) { - frameState.push(kind, frameState.loadLocal(index)); - } - - private void storeLocal(Kind kind, int index) { - ValueNode value; - if (kind == Kind.Object) { - value = frameState.xpop(); - // astore and astore_ may be used to store a returnAddress (jsr) - assert value.kind() == Kind.Object || value.kind() == Kind.Int; - } else { - value = frameState.pop(kind); - } - frameState.storeLocal(index, value); - } - - public static boolean covers(ExceptionHandler handler, int bci) { - return handler.getStartBCI() <= bci && bci < handler.getEndBCI(); - } - - public static boolean isCatchAll(ExceptionHandler handler) { - return handler.catchTypeCPI() == 0; - } - - /** - * @param type the unresolved type of the constant - */ - protected void handleUnresolvedLoadConstant(JavaType type) { - assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - frameState.push(Kind.Object, appendConstant(Constant.NULL_OBJECT)); - } - - /** - * @param type the unresolved type of the type check - * @param object the object value whose type is being checked against {@code type} - */ - protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { - assert !graphBuilderConfig.eagerResolving(); - append(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), Unresolved, InvalidateRecompile)); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); - } - - /** - * @param type the unresolved type of the type check - * @param object the object value whose type is being checked against {@code type} - */ - protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) { - assert !graphBuilderConfig.eagerResolving(); - BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode(this)); - DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - append(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); - lastInstr = successor; - frameState.ipush(appendConstant(Constant.INT_0)); - } - - /** - * @param type the type being instantiated - */ - protected void handleUnresolvedNewInstance(JavaType type) { - assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); - } - - /** - * @param type the type of the array being instantiated - * @param length the length of the array - */ - protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) { - assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); - } - - /** - * @param type the type being instantiated - * @param dims the dimensions for the multi-array - */ - protected void handleUnresolvedNewMultiArray(JavaType type, ValueNode[] dims) { - assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); - } - - /** - * @param field the unresolved field - * @param receiver the object containing the field or {@code null} if {@code field} is static - */ - protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) { - assert !graphBuilderConfig.eagerResolving(); - Kind kind = field.getKind(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - frameState.push(kind.getStackKind(), appendConstant(Constant.defaultForKind(kind))); - } - - /** - * @param field the unresolved field - * @param value the value being stored to the field - * @param receiver the object containing the field or {@code null} if {@code field} is static - */ - protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) { - assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - } - - /** - * @param representation - * @param type - */ - protected void handleUnresolvedExceptionType(Representation representation, JavaType type) { - assert !graphBuilderConfig.eagerResolving(); - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - } - - protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) { - assert !graphBuilderConfig.eagerResolving(); - boolean withReceiver = invokeKind != InvokeKind.Static; - append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - frameState.popArguments(javaMethod.getSignature().getParameterSlots(withReceiver), javaMethod.getSignature().getParameterCount(withReceiver)); - Kind kind = javaMethod.getSignature().getReturnKind(); - if (kind != Kind.Void) { - frameState.push(kind.getStackKind(), appendConstant(Constant.defaultForKind(kind))); - } - } - - private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) { - assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci"; - Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci)); - - Block dispatchBlock = currentBlock.exceptionDispatchBlock(); - // The exception dispatch block is always for the last bytecode of a block, so if we are not - // at the endBci yet, - // there is no exception handler for this bci and we can unwind immediately. - if (bci != currentBlock.endBci || dispatchBlock == null) { - dispatchBlock = unwindBlock(bci); - } - - FrameStateBuilder dispatchState = frameState.copy(); - dispatchState.clearStack(); - - DispatchBeginNode dispatchBegin; - if (exceptionObject == null) { - dispatchBegin = currentGraph.add(new ExceptionObjectNode(metaAccess)); - dispatchState.apush(dispatchBegin); - dispatchState.setRethrowException(true); - dispatchBegin.setStateAfter(dispatchState.create(bci)); - } else { - dispatchBegin = currentGraph.add(new DispatchBeginNode()); - dispatchBegin.setStateAfter(dispatchState.create(bci)); - dispatchState.apush(exceptionObject); - dispatchState.setRethrowException(true); - } - FixedNode target = createTarget(dispatchBlock, dispatchState); - dispatchBegin.setNext(target); - return dispatchBegin; + protected void run(StructuredGraph graph, HighTierContext context) { + new Instance(context.getMetaAccess(), graphBuilderConfig, context.getOptimisticOptimizations()).run(graph); } - private void genLoadConstant(int cpi, int opcode) { - Object con = lookupConstant(cpi, opcode); + public static class Instance extends Phase { + + private LineNumberTable lnt; + private int previousLineNumber; + private int currentLineNumber; + + protected StructuredGraph currentGraph; + + /** + * Head of placeholder list. + */ + protected BlockPlaceholderNode placeholders; + + private final MetaAccessProvider metaAccess; + private ConstantPool constantPool; + private ResolvedJavaMethod method; + private int entryBCI; + private ProfilingInfo profilingInfo; + + private BytecodeStream stream; // the bytecode stream + + protected FrameStateBuilder frameState; // the current execution state + private Block currentBlock; + + private ValueNode methodSynchronizedObject; + private ExceptionDispatchBlock unwindBlock; + private Block returnBlock; - if (con instanceof JavaType) { - // this is a load of class constant which might be unresolved - JavaType type = (JavaType) con; - if (type instanceof ResolvedJavaType) { - frameState.push(Kind.Object, appendConstant(((ResolvedJavaType) type).getEncoding(Representation.JavaClass))); - } else { - handleUnresolvedLoadConstant(type); + private FixedWithNextNode lastInstr; // the last instruction added + + private final GraphBuilderConfiguration graphBuilderConfig; + private final OptimisticOptimizations optimisticOpts; + + /** + * Meters the number of actual bytecodes parsed. + */ + public static final DebugMetric BytecodesParsed = Debug.metric("BytecodesParsed"); + + /** + * Node that marks the begin of block during bytecode parsing. When a block is identified + * the first time as a jump target, the placeholder is created and used as the successor for + * the jump. When the block is seen the second time, a {@link MergeNode} is created to + * correctly merge the now two different predecessor states. + */ + private static class BlockPlaceholderNode extends FixedWithNextNode { + + /* + * Cannot be explicitly declared as a Node type since it is not an input; would cause + * the !NODE_CLASS.isAssignableFrom(type) guarantee in + * NodeClass.FieldScanner.scanField() to fail. + */ + private final Object nextPlaceholder; + + public BlockPlaceholderNode(Instance builder) { + super(StampFactory.forVoid()); + nextPlaceholder = builder.placeholders; + builder.placeholders = this; } - } else if (con instanceof Constant) { - Constant constant = (Constant) con; - frameState.push(constant.getKind().getStackKind(), appendConstant(constant)); - } else { - throw new Error("lookupConstant returned an object of incorrect type"); + + BlockPlaceholderNode nextPlaceholder() { + return (BlockPlaceholderNode) nextPlaceholder; + } } - } + + private Block[] loopHeaders; + + /** + * Gets the current frame state being processed by this builder. + */ + protected FrameStateBuilder getCurrentFrameState() { + return frameState; + } - private void genLoadIndexed(Kind kind) { - emitExplicitExceptions(frameState.peek(1), frameState.peek(0)); + /** + * Gets the graph being processed by this builder. + */ + protected StructuredGraph getGraph() { + return currentGraph; + } + + protected ResolvedJavaMethod getMethod() { + return method; + } - ValueNode index = frameState.ipop(); - ValueNode array = frameState.apop(); - frameState.push(kind.getStackKind(), append(new LoadIndexedNode(array, index, kind))); - } + public Instance(MetaAccessProvider metaAccess, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { + this.graphBuilderConfig = graphBuilderConfig; + this.optimisticOpts = optimisticOpts; + this.metaAccess = metaAccess; + assert metaAccess != null; + } - private void genStoreIndexed(Kind kind) { - emitExplicitExceptions(frameState.peek(2), frameState.peek(1)); + @Override + protected void run(StructuredGraph graph) { + method = graph.method(); + if (graphBuilderConfig.eagerInfopointMode()) { + lnt = method.getLineNumberTable(); + previousLineNumber = -1; + } + entryBCI = graph.getEntryBCI(); + profilingInfo = method.getProfilingInfo(); + assert method.getCode() != null : "method must contain bytecodes: " + method; + this.stream = new BytecodeStream(method.getCode()); + this.constantPool = method.getConstantPool(); + unwindBlock = null; + returnBlock = null; + methodSynchronizedObject = null; + this.currentGraph = graph; + this.frameState = new FrameStateBuilder(method, graph, graphBuilderConfig.eagerResolving()); + TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); + try { + build(); + } finally { + filter.remove(); + } + } - ValueNode value = frameState.pop(kind.getStackKind()); - ValueNode index = frameState.ipop(); - ValueNode array = frameState.apop(); - append(new StoreIndexedNode(array, index, kind, value)); - } + @Override + protected String getDetailedName() { + return getName() + " " + MetaUtil.format("%H.%n(%p):%r", method); + } + + private BciBlockMapping createBlockMap() { + BciBlockMapping map = new BciBlockMapping(method); + map.build(); + if (Debug.isDumpEnabled()) { + Debug.dump(map, MetaUtil.format("After block building %f %R %H.%n(%P)", method)); + } - private void stackOp(int opcode) { - switch (opcode) { - case POP: { - frameState.xpop(); - break; + return map; + } + + protected void build() { + if (PrintProfilingInformation.getValue()) { + TTY.println("Profiling info for " + MetaUtil.format("%H.%n(%p)", method)); + TTY.println(MetaUtil.indent(MetaUtil.profileToString(profilingInfo, method, CodeUtil.NEW_LINE), " ")); + } + + Indent indent = Debug.logAndIndent("build graph for %s", method); + + // compute the block map, setup exception handlers and get the entrypoint(s) + BciBlockMapping blockMap = createBlockMap(); + loopHeaders = blockMap.loopHeaders; + + lastInstr = currentGraph.start(); + if (isSynchronized(method.getModifiers())) { + // add a monitor enter to the start block + currentGraph.start().setStateAfter(frameState.create(FrameState.BEFORE_BCI)); + methodSynchronizedObject = synchronizedObject(frameState, method); + lastInstr = genMonitorEnter(methodSynchronizedObject); } - case POP2: { - frameState.xpop(); - frameState.xpop(); - break; + frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn); + ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); + + if (graphBuilderConfig.eagerInfopointMode()) { + InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START, frameState.create(0))); + lastInstr.setNext(ipn); + lastInstr = ipn; } - case DUP: { - ValueNode w = frameState.xpop(); - frameState.xpush(w); - frameState.xpush(w); - break; + + currentBlock = blockMap.startBlock; + blockMap.startBlock.entryState = frameState; + if (blockMap.startBlock.isLoopHeader) { + /* + * TODO(lstadler,gduboscq) createTarget might not be safe at this position, since it + * expects currentBlock, etc. to be set up correctly. A better solution to this + * problem of start blocks that are loop headers would be to create a dummy block in + * BciBlockMapping. + */ + appendGoto(createTarget(blockMap.startBlock, frameState)); + } else { + blockMap.startBlock.firstInstruction = lastInstr; + } + + for (Block block : blockMap.blocks) { + processBlock(block); } - case DUP_X1: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - frameState.xpush(w1); - frameState.xpush(w2); - frameState.xpush(w1); - break; + processBlock(returnBlock); + processBlock(unwindBlock); + + Debug.dump(currentGraph, "After bytecode parsing"); + + connectLoopEndToBegin(); + + // remove Placeholders + for (BlockPlaceholderNode n = placeholders; n != null; n = n.nextPlaceholder()) { + if (!n.isDeleted()) { + currentGraph.removeFixed(n); + } + } + placeholders = null; + + // remove dead FrameStates + for (Node n : currentGraph.getNodes(FrameState.class)) { + if (n.usages().isEmpty() && n.predecessor() == null) { + n.safeDelete(); + } + } + indent.outdent(); + } + + private Block unwindBlock(int bci) { + if (unwindBlock == null) { + unwindBlock = new ExceptionDispatchBlock(); + unwindBlock.startBci = -1; + unwindBlock.endBci = -1; + unwindBlock.deoptBci = bci; + unwindBlock.blockID = Integer.MAX_VALUE; } - case DUP_X2: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - ValueNode w3 = frameState.xpop(); - frameState.xpush(w1); - frameState.xpush(w3); - frameState.xpush(w2); - frameState.xpush(w1); - break; + return unwindBlock; + } + + private Block returnBlock(int bci) { + if (returnBlock == null) { + returnBlock = new Block(); + returnBlock.startBci = bci; + returnBlock.endBci = bci; + returnBlock.blockID = Integer.MAX_VALUE; } - case DUP2: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - frameState.xpush(w2); - frameState.xpush(w1); - frameState.xpush(w2); - frameState.xpush(w1); - break; + return returnBlock; + } + + public BytecodeStream stream() { + return stream; + } + + public int bci() { + return stream.currentBCI(); + } + + private void loadLocal(int index, Kind kind) { + frameState.push(kind, frameState.loadLocal(index)); + } + + private void storeLocal(Kind kind, int index) { + ValueNode value; + if (kind == Kind.Object) { + value = frameState.xpop(); + // astore and astore_ may be used to store a returnAddress (jsr) + assert value.kind() == Kind.Object || value.kind() == Kind.Int; + } else { + value = frameState.pop(kind); } - case DUP2_X1: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - ValueNode w3 = frameState.xpop(); - frameState.xpush(w2); - frameState.xpush(w1); - frameState.xpush(w3); - frameState.xpush(w2); - frameState.xpush(w1); - break; + frameState.storeLocal(index, value); + } + + public static boolean covers(ExceptionHandler handler, int bci) { + return handler.getStartBCI() <= bci && bci < handler.getEndBCI(); + } + + public static boolean isCatchAll(ExceptionHandler handler) { + return handler.catchTypeCPI() == 0; + } + + /** + * @param type the unresolved type of the constant + */ + protected void handleUnresolvedLoadConstant(JavaType type) { + assert !graphBuilderConfig.eagerResolving(); + append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + frameState.push(Kind.Object, appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the unresolved type of the type check + * @param object the object value whose type is being checked against {@code type} + */ + protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { + assert !graphBuilderConfig.eagerResolving(); + append(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), Unresolved, InvalidateRecompile)); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the unresolved type of the type check + * @param object the object value whose type is being checked against {@code type} + */ + protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) { + assert !graphBuilderConfig.eagerResolving(); + BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode(this)); + DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + append(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); + lastInstr = successor; + frameState.ipush(appendConstant(Constant.INT_0)); + } + + /** + * @param type the type being instantiated + */ + protected void handleUnresolvedNewInstance(JavaType type) { + assert !graphBuilderConfig.eagerResolving(); + append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the type of the array being instantiated + * @param length the length of the array + */ + protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) { + assert !graphBuilderConfig.eagerResolving(); + append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the type being instantiated + * @param dims the dimensions for the multi-array + */ + protected void handleUnresolvedNewMultiArray(JavaType type, ValueNode[] dims) { + assert !graphBuilderConfig.eagerResolving(); + append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param field the unresolved field + * @param receiver the object containing the field or {@code null} if {@code field} is + * static + */ + protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) { + assert !graphBuilderConfig.eagerResolving(); + Kind kind = field.getKind(); + append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + frameState.push(kind.getStackKind(), appendConstant(Constant.defaultForKind(kind))); + } + + /** + * @param field the unresolved field + * @param value the value being stored to the field + * @param receiver the object containing the field or {@code null} if {@code field} is + * static + */ + protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) { + assert !graphBuilderConfig.eagerResolving(); + append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + } + + /** + * @param representation + * @param type + */ + protected void handleUnresolvedExceptionType(Representation representation, JavaType type) { + assert !graphBuilderConfig.eagerResolving(); + append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + } + + protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) { + assert !graphBuilderConfig.eagerResolving(); + boolean withReceiver = invokeKind != InvokeKind.Static; + append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); + frameState.popArguments(javaMethod.getSignature().getParameterSlots(withReceiver), javaMethod.getSignature().getParameterCount(withReceiver)); + Kind kind = javaMethod.getSignature().getReturnKind(); + if (kind != Kind.Void) { + frameState.push(kind.getStackKind(), appendConstant(Constant.defaultForKind(kind))); } - case DUP2_X2: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - ValueNode w3 = frameState.xpop(); - ValueNode w4 = frameState.xpop(); - frameState.xpush(w2); - frameState.xpush(w1); - frameState.xpush(w4); - frameState.xpush(w3); - frameState.xpush(w2); - frameState.xpush(w1); - break; - } - case SWAP: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - frameState.xpush(w1); - frameState.xpush(w2); - break; - } - default: - throw GraalInternalError.shouldNotReachHere(); } - } + private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) { + assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci"; + Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci)); + + Block dispatchBlock = currentBlock.exceptionDispatchBlock(); + /* + * The exception dispatch block is always for the last bytecode of a block, so if we are + * not at the endBci yet, there is no exception handler for this bci and we can unwind + * immediately. + */ + if (bci != currentBlock.endBci || dispatchBlock == null) { + dispatchBlock = unwindBlock(bci); + } + + FrameStateBuilder dispatchState = frameState.copy(); + dispatchState.clearStack(); + + DispatchBeginNode dispatchBegin; + if (exceptionObject == null) { + dispatchBegin = currentGraph.add(new ExceptionObjectNode(metaAccess)); + dispatchState.apush(dispatchBegin); + dispatchState.setRethrowException(true); + dispatchBegin.setStateAfter(dispatchState.create(bci)); + } else { + dispatchBegin = currentGraph.add(new DispatchBeginNode()); + dispatchBegin.setStateAfter(dispatchState.create(bci)); + dispatchState.apush(exceptionObject); + dispatchState.setRethrowException(true); + } + FixedNode target = createTarget(dispatchBlock, dispatchState); + dispatchBegin.setNext(target); + return dispatchBegin; + } - private void genArithmeticOp(Kind result, int opcode) { - ValueNode y = frameState.pop(result); - ValueNode x = frameState.pop(result); - boolean isStrictFP = isStrict(method.getModifiers()); - BinaryNode v; - switch (opcode) { - case IADD: - case LADD: - v = new IntegerAddNode(result, x, y); - break; - case FADD: - case DADD: - v = new FloatAddNode(result, x, y, isStrictFP); - break; - case ISUB: - case LSUB: - v = new IntegerSubNode(result, x, y); - break; - case FSUB: - case DSUB: - v = new FloatSubNode(result, x, y, isStrictFP); - break; - case IMUL: - case LMUL: - v = new IntegerMulNode(result, x, y); - break; - case FMUL: - case DMUL: - v = new FloatMulNode(result, x, y, isStrictFP); - break; - case FDIV: - case DDIV: - v = new FloatDivNode(result, x, y, isStrictFP); - break; - case FREM: - case DREM: - v = new FloatRemNode(result, x, y, isStrictFP); - break; - default: - throw new GraalInternalError("should not reach"); + private void genLoadConstant(int cpi, int opcode) { + Object con = lookupConstant(cpi, opcode); + + if (con instanceof JavaType) { + // this is a load of class constant which might be unresolved + JavaType type = (JavaType) con; + if (type instanceof ResolvedJavaType) { + frameState.push(Kind.Object, appendConstant(((ResolvedJavaType) type).getEncoding(Representation.JavaClass))); + } else { + handleUnresolvedLoadConstant(type); + } + } else if (con instanceof Constant) { + Constant constant = (Constant) con; + frameState.push(constant.getKind().getStackKind(), appendConstant(constant)); + } else { + throw new Error("lookupConstant returned an object of incorrect type"); + } } - frameState.push(result, append(v)); - } + + private void genLoadIndexed(Kind kind) { + emitExplicitExceptions(frameState.peek(1), frameState.peek(0)); + + ValueNode index = frameState.ipop(); + ValueNode array = frameState.apop(); + frameState.push(kind.getStackKind(), append(new LoadIndexedNode(array, index, kind))); + } - private void genIntegerDivOp(Kind result, int opcode) { - ValueNode y = frameState.pop(result); - ValueNode x = frameState.pop(result); - FixedWithNextNode v; - switch (opcode) { - case IDIV: - case LDIV: - v = new IntegerDivNode(result, x, y); - break; - case IREM: - case LREM: - v = new IntegerRemNode(result, x, y); - break; - default: - throw new GraalInternalError("should not reach"); + private void genStoreIndexed(Kind kind) { + emitExplicitExceptions(frameState.peek(2), frameState.peek(1)); + + ValueNode value = frameState.pop(kind.getStackKind()); + ValueNode index = frameState.ipop(); + ValueNode array = frameState.apop(); + append(new StoreIndexedNode(array, index, kind, value)); } - frameState.push(result, append(v)); - } - - private void genNegateOp(Kind kind) { - frameState.push(kind, append(new NegateNode(frameState.pop(kind)))); - } - private void genShiftOp(Kind kind, int opcode) { - ValueNode s = frameState.ipop(); - ValueNode x = frameState.pop(kind); - ShiftNode v; - switch (opcode) { - case ISHL: - case LSHL: - v = new LeftShiftNode(kind, x, s); - break; - case ISHR: - case LSHR: - v = new RightShiftNode(kind, x, s); - break; - case IUSHR: - case LUSHR: - v = new UnsignedRightShiftNode(kind, x, s); - break; - default: - throw new GraalInternalError("should not reach"); - } - frameState.push(kind, append(v)); - } + private void stackOp(int opcode) { + switch (opcode) { + case POP: { + frameState.xpop(); + break; + } + case POP2: { + frameState.xpop(); + frameState.xpop(); + break; + } + case DUP: { + ValueNode w = frameState.xpop(); + frameState.xpush(w); + frameState.xpush(w); + break; + } + case DUP_X1: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP_X2: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP2: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP2_X1: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP2_X2: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); + ValueNode w4 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w4); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case SWAP: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w2); + break; + } + default: + throw GraalInternalError.shouldNotReachHere(); + } - private void genLogicOp(Kind kind, int opcode) { - ValueNode y = frameState.pop(kind); - ValueNode x = frameState.pop(kind); - BitLogicNode v; - switch (opcode) { - case IAND: - case LAND: - v = new AndNode(kind, x, y); - break; - case IOR: - case LOR: - v = new OrNode(kind, x, y); - break; - case IXOR: - case LXOR: - v = new XorNode(kind, x, y); - break; - default: - throw new GraalInternalError("should not reach"); } - frameState.push(kind, append(v)); - } - private void genCompareOp(Kind kind, boolean isUnorderedLess) { - ValueNode y = frameState.pop(kind); - ValueNode x = frameState.pop(kind); - frameState.ipush(append(new NormalizeCompareNode(x, y, isUnorderedLess))); - } - - private void genConvert(Kind from, Kind to) { - ValueNode input = frameState.pop(from.getStackKind()); - frameState.push(to.getStackKind(), append(new ConvertNode(from, to, input))); - } - - private void genIncrement() { - int index = stream().readLocalIndex(); - int delta = stream().readIncrement(); - ValueNode x = frameState.loadLocal(index); - ValueNode y = appendConstant(Constant.forInt(delta)); - frameState.storeLocal(index, append(new IntegerAddNode(Kind.Int, x, y))); - } - - private void genGoto() { - appendGoto(createTarget(currentBlock.successors.get(0), frameState)); - assert currentBlock.numNormalSuccessors() == 1; - } - - private void ifNode(ValueNode x, Condition cond, ValueNode y) { - assert !x.isDeleted() && !y.isDeleted(); - assert currentBlock.numNormalSuccessors() == 2; - Block trueBlock = currentBlock.successors.get(0); - Block falseBlock = currentBlock.successors.get(1); - if (trueBlock == falseBlock) { - appendGoto(createTarget(trueBlock, frameState)); - return; + private void genArithmeticOp(Kind result, int opcode) { + ValueNode y = frameState.pop(result); + ValueNode x = frameState.pop(result); + boolean isStrictFP = isStrict(method.getModifiers()); + BinaryNode v; + switch (opcode) { + case IADD: + case LADD: + v = new IntegerAddNode(result, x, y); + break; + case FADD: + case DADD: + v = new FloatAddNode(result, x, y, isStrictFP); + break; + case ISUB: + case LSUB: + v = new IntegerSubNode(result, x, y); + break; + case FSUB: + case DSUB: + v = new FloatSubNode(result, x, y, isStrictFP); + break; + case IMUL: + case LMUL: + v = new IntegerMulNode(result, x, y); + break; + case FMUL: + case DMUL: + v = new FloatMulNode(result, x, y, isStrictFP); + break; + case FDIV: + case DDIV: + v = new FloatDivNode(result, x, y, isStrictFP); + break; + case FREM: + case DREM: + v = new FloatRemNode(result, x, y, isStrictFP); + break; + default: + throw new GraalInternalError("should not reach"); + } + frameState.push(result, append(v)); } - double probability = profilingInfo.getBranchTakenProbability(bci()); - if (probability < 0) { - assert probability == -1 : "invalid probability"; - Debug.log("missing probability in %s at bci %d", method, bci()); - probability = 0.5; + private void genIntegerDivOp(Kind result, int opcode) { + ValueNode y = frameState.pop(result); + ValueNode x = frameState.pop(result); + FixedWithNextNode v; + switch (opcode) { + case IDIV: + case LDIV: + v = new IntegerDivNode(result, x, y); + break; + case IREM: + case LREM: + v = new IntegerRemNode(result, x, y); + break; + default: + throw new GraalInternalError("should not reach"); + } + frameState.push(result, append(v)); + } + + private void genNegateOp(Kind kind) { + frameState.push(kind, append(new NegateNode(frameState.pop(kind)))); + } + + private void genShiftOp(Kind kind, int opcode) { + ValueNode s = frameState.ipop(); + ValueNode x = frameState.pop(kind); + ShiftNode v; + switch (opcode) { + case ISHL: + case LSHL: + v = new LeftShiftNode(kind, x, s); + break; + case ISHR: + case LSHR: + v = new RightShiftNode(kind, x, s); + break; + case IUSHR: + case LUSHR: + v = new UnsignedRightShiftNode(kind, x, s); + break; + default: + throw new GraalInternalError("should not reach"); + } + frameState.push(kind, append(v)); + } + + private void genLogicOp(Kind kind, int opcode) { + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); + BitLogicNode v; + switch (opcode) { + case IAND: + case LAND: + v = new AndNode(kind, x, y); + break; + case IOR: + case LOR: + v = new OrNode(kind, x, y); + break; + case IXOR: + case LXOR: + v = new XorNode(kind, x, y); + break; + default: + throw new GraalInternalError("should not reach"); + } + frameState.push(kind, append(v)); + } + + private void genCompareOp(Kind kind, boolean isUnorderedLess) { + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); + frameState.ipush(append(new NormalizeCompareNode(x, y, isUnorderedLess))); + } + + private void genConvert(Kind from, Kind to) { + ValueNode input = frameState.pop(from.getStackKind()); + frameState.push(to.getStackKind(), append(new ConvertNode(from, to, input))); + } + + private void genIncrement() { + int index = stream().readLocalIndex(); + int delta = stream().readIncrement(); + ValueNode x = frameState.loadLocal(index); + ValueNode y = appendConstant(Constant.forInt(delta)); + frameState.storeLocal(index, append(new IntegerAddNode(Kind.Int, x, y))); + } + + private void genGoto() { + appendGoto(createTarget(currentBlock.successors.get(0), frameState)); + assert currentBlock.numNormalSuccessors() == 1; } - if (!optimisticOpts.removeNeverExecutedCode()) { - if (probability == 0) { - probability = 0.0000001; - } else if (probability == 1) { - probability = 0.999999; + private void ifNode(ValueNode x, Condition cond, ValueNode y) { + assert !x.isDeleted() && !y.isDeleted(); + assert currentBlock.numNormalSuccessors() == 2; + Block trueBlock = currentBlock.successors.get(0); + Block falseBlock = currentBlock.successors.get(1); + if (trueBlock == falseBlock) { + appendGoto(createTarget(trueBlock, frameState)); + return; + } + + double probability = profilingInfo.getBranchTakenProbability(bci()); + if (probability < 0) { + assert probability == -1 : "invalid probability"; + Debug.log("missing probability in %s at bci %d", method, bci()); + probability = 0.5; + } + + if (!optimisticOpts.removeNeverExecutedCode()) { + if (probability == 0) { + probability = 0.0000001; + } else if (probability == 1) { + probability = 0.999999; + } + } + + // the mirroring and negation operations get the condition into canonical form + boolean mirror = cond.canonicalMirror(); + boolean negate = cond.canonicalNegate(); + + ValueNode a = mirror ? y : x; + ValueNode b = mirror ? x : y; + + CompareNode condition; + assert !a.kind().isNumericFloat(); + if (cond == Condition.EQ || cond == Condition.NE) { + if (a.kind() == Kind.Object) { + condition = new ObjectEqualsNode(a, b); + } else { + condition = new IntegerEqualsNode(a, b); + } + } else { + assert a.kind() != Kind.Object && !cond.isUnsigned(); + condition = new IntegerLessThanNode(a, b); + } + condition = currentGraph.unique(condition); + + AbstractBeginNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState); + AbstractBeginNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState); + + IfNode ifNode = negate ? new IfNode(condition, falseSuccessor, trueSuccessor, 1 - probability) : new IfNode(condition, trueSuccessor, falseSuccessor, probability); + append(ifNode); + } + + private void genIfZero(Condition cond) { + ValueNode y = appendConstant(Constant.INT_0); + ValueNode x = frameState.ipop(); + ifNode(x, cond, y); + } + + private void genIfNull(Condition cond) { + ValueNode y = appendConstant(Constant.NULL_OBJECT); + ValueNode x = frameState.apop(); + ifNode(x, cond, y); + } + + private void genIfSame(Kind kind, Condition cond) { + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); + assert !x.isDeleted() && !y.isDeleted(); + ifNode(x, cond, y); + } + + private void genThrow() { + ValueNode exception = frameState.apop(); + append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); + lastInstr.setNext(handleException(exception, bci())); + } + + private JavaType lookupType(int cpi, int bytecode) { + eagerResolvingForSnippets(cpi, bytecode); + JavaType result = constantPool.lookupType(cpi, bytecode); + assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType; + return result; + } + + private JavaMethod lookupMethod(int cpi, int opcode) { + eagerResolvingForSnippets(cpi, opcode); + JavaMethod result = constantPool.lookupMethod(cpi, opcode); + /* + * assert !graphBuilderConfig.unresolvedIsError() || ((result instanceof + * ResolvedJavaMethod) && ((ResolvedJavaMethod) + * result).getDeclaringClass().isInitialized()) : result; + */ + return result; + } + + private JavaField lookupField(int cpi, int opcode) { + eagerResolvingForSnippets(cpi, opcode); + JavaField result = constantPool.lookupField(cpi, opcode); + assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; + return result; + } + + private Object lookupConstant(int cpi, int opcode) { + eagerResolvingForSnippets(cpi, opcode); + Object result = constantPool.lookupConstant(cpi); + assert !graphBuilderConfig.eagerResolving() || !(result instanceof JavaType) || (result instanceof ResolvedJavaType); + return result; + } + + private void eagerResolvingForSnippets(int cpi, int bytecode) { + if (graphBuilderConfig.eagerResolving()) { + constantPool.loadReferencedType(cpi, bytecode); + } + } + + private JavaTypeProfile getProfileForTypeCheck(ResolvedJavaType type) { + if (!optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) { + return null; + } else { + return profilingInfo.getTypeProfile(bci()); } } - // the mirroring and negation operations get the condition into canonical form - boolean mirror = cond.canonicalMirror(); - boolean negate = cond.canonicalNegate(); - - ValueNode a = mirror ? y : x; - ValueNode b = mirror ? x : y; - - CompareNode condition; - assert !a.kind().isNumericFloat(); - if (cond == Condition.EQ || cond == Condition.NE) { - if (a.kind() == Kind.Object) { - condition = new ObjectEqualsNode(a, b); + private void genCheckCast() { + int cpi = stream().readCPI(); + JavaType type = lookupType(cpi, CHECKCAST); + ValueNode object = frameState.apop(); + if (type instanceof ResolvedJavaType) { + JavaTypeProfile profileForTypeCheck = getProfileForTypeCheck((ResolvedJavaType) type); + CheckCastNode checkCastNode = append(new CheckCastNode((ResolvedJavaType) type, object, profileForTypeCheck, false)); + frameState.apush(checkCastNode); } else { - condition = new IntegerEqualsNode(a, b); + handleUnresolvedCheckCast(type, object); } - } else { - assert a.kind() != Kind.Object && !cond.isUnsigned(); - condition = new IntegerLessThanNode(a, b); } - condition = currentGraph.unique(condition); - - AbstractBeginNode trueSuccessor = createBlockTarget(probability, trueBlock, frameState); - AbstractBeginNode falseSuccessor = createBlockTarget(1 - probability, falseBlock, frameState); - - IfNode ifNode = negate ? new IfNode(condition, falseSuccessor, trueSuccessor, 1 - probability) : new IfNode(condition, trueSuccessor, falseSuccessor, probability); - append(ifNode); - } - - private void genIfZero(Condition cond) { - ValueNode y = appendConstant(Constant.INT_0); - ValueNode x = frameState.ipop(); - ifNode(x, cond, y); - } - - private void genIfNull(Condition cond) { - ValueNode y = appendConstant(Constant.NULL_OBJECT); - ValueNode x = frameState.apop(); - ifNode(x, cond, y); - } - private void genIfSame(Kind kind, Condition cond) { - ValueNode y = frameState.pop(kind); - ValueNode x = frameState.pop(kind); - assert !x.isDeleted() && !y.isDeleted(); - ifNode(x, cond, y); - } - - private void genThrow() { - ValueNode exception = frameState.apop(); - append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); - lastInstr.setNext(handleException(exception, bci())); - } - - private JavaType lookupType(int cpi, int bytecode) { - eagerResolvingForSnippets(cpi, bytecode); - JavaType result = constantPool.lookupType(cpi, bytecode); - assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType; - return result; - } + private void genInstanceOf() { + int cpi = stream().readCPI(); + JavaType type = lookupType(cpi, INSTANCEOF); + ValueNode object = frameState.apop(); + if (type instanceof ResolvedJavaType) { + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + InstanceOfNode instanceOfNode = new InstanceOfNode((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); + frameState.ipush(append(new ConditionalNode(currentGraph.unique(instanceOfNode)))); + } else { + handleUnresolvedInstanceOf(type, object); + } + } - private JavaMethod lookupMethod(int cpi, int opcode) { - eagerResolvingForSnippets(cpi, opcode); - JavaMethod result = constantPool.lookupMethod(cpi, opcode); - // assert !graphBuilderConfig.unresolvedIsError() || ((result instanceof ResolvedJavaMethod) - // && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result; - return result; - } + void genNewInstance(int cpi) { + JavaType type = lookupType(cpi, NEW); + if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) { + frameState.apush(append(createNewInstance((ResolvedJavaType) type, true))); + } else { + handleUnresolvedNewInstance(type); + } + } - private JavaField lookupField(int cpi, int opcode) { - eagerResolvingForSnippets(cpi, opcode); - JavaField result = constantPool.lookupField(cpi, opcode); - assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; - return result; - } - - private Object lookupConstant(int cpi, int opcode) { - eagerResolvingForSnippets(cpi, opcode); - Object result = constantPool.lookupConstant(cpi); - assert !graphBuilderConfig.eagerResolving() || !(result instanceof JavaType) || (result instanceof ResolvedJavaType); - return result; - } - - private void eagerResolvingForSnippets(int cpi, int bytecode) { - if (graphBuilderConfig.eagerResolving()) { - constantPool.loadReferencedType(cpi, bytecode); + protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) { + return new NewInstanceNode(type, fillContents); } - } - private JavaTypeProfile getProfileForTypeCheck(ResolvedJavaType type) { - if (!optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) { - return null; - } else { - return profilingInfo.getTypeProfile(bci()); - } - } - - private void genCheckCast() { - int cpi = stream().readCPI(); - JavaType type = lookupType(cpi, CHECKCAST); - ValueNode object = frameState.apop(); - if (type instanceof ResolvedJavaType) { - JavaTypeProfile profileForTypeCheck = getProfileForTypeCheck((ResolvedJavaType) type); - CheckCastNode checkCastNode = append(new CheckCastNode((ResolvedJavaType) type, object, profileForTypeCheck, false)); - frameState.apush(checkCastNode); - } else { - handleUnresolvedCheckCast(type, object); + /** + * Gets the kind of array elements for the array type code that appears in a + * {@link Bytecodes#NEWARRAY} bytecode. + * + * @param code the array type code + * @return the kind from the array type code + */ + public static Class arrayTypeCodeToClass(int code) { + // Checkstyle: stop + switch (code) { + case 4: + return boolean.class; + case 5: + return char.class; + case 6: + return float.class; + case 7: + return double.class; + case 8: + return byte.class; + case 9: + return short.class; + case 10: + return int.class; + case 11: + return long.class; + default: + throw new IllegalArgumentException("unknown array type code: " + code); + } + // Checkstyle: resume } - } - - private void genInstanceOf() { - int cpi = stream().readCPI(); - JavaType type = lookupType(cpi, INSTANCEOF); - ValueNode object = frameState.apop(); - if (type instanceof ResolvedJavaType) { - ResolvedJavaType resolvedType = (ResolvedJavaType) type; - InstanceOfNode instanceOfNode = new InstanceOfNode((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); - frameState.ipush(append(new ConditionalNode(currentGraph.unique(instanceOfNode)))); - } else { - handleUnresolvedInstanceOf(type, object); - } - } - - void genNewInstance(int cpi) { - JavaType type = lookupType(cpi, NEW); - if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) { - frameState.apush(append(createNewInstance((ResolvedJavaType) type, true))); - } else { - handleUnresolvedNewInstance(type); - } - } - protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) { - return new NewInstanceNode(type, fillContents); - } + private void genNewPrimitiveArray(int typeCode) { + Class clazz = arrayTypeCodeToClass(typeCode); + ResolvedJavaType elementType = metaAccess.lookupJavaType(clazz); + frameState.apush(append(createNewArray(elementType, frameState.ipop(), true))); + } - /** - * Gets the kind of array elements for the array type code that appears in a - * {@link Bytecodes#NEWARRAY} bytecode. - * - * @param code the array type code - * @return the kind from the array type code - */ - public static Class arrayTypeCodeToClass(int code) { - // Checkstyle: stop - switch (code) { - case 4: - return boolean.class; - case 5: - return char.class; - case 6: - return float.class; - case 7: - return double.class; - case 8: - return byte.class; - case 9: - return short.class; - case 10: - return int.class; - case 11: - return long.class; - default: - throw new IllegalArgumentException("unknown array type code: " + code); + private void genNewObjectArray(int cpi) { + JavaType type = lookupType(cpi, ANEWARRAY); + ValueNode length = frameState.ipop(); + if (type instanceof ResolvedJavaType) { + frameState.apush(append(createNewArray((ResolvedJavaType) type, length, true))); + } else { + handleUnresolvedNewObjectArray(type, length); + } + } - // Checkstyle: resume - } - private void genNewPrimitiveArray(int typeCode) { - Class clazz = arrayTypeCodeToClass(typeCode); - ResolvedJavaType elementType = metaAccess.lookupJavaType(clazz); - frameState.apush(append(createNewArray(elementType, frameState.ipop(), true))); - } - - private void genNewObjectArray(int cpi) { - JavaType type = lookupType(cpi, ANEWARRAY); - ValueNode length = frameState.ipop(); - if (type instanceof ResolvedJavaType) { - frameState.apush(append(createNewArray((ResolvedJavaType) type, length, true))); - } else { - handleUnresolvedNewObjectArray(type, length); + protected NewArrayNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { + return new NewArrayNode(elementType, length, fillContents); } - } - - protected NewArrayNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { - return new NewArrayNode(elementType, length, fillContents); - } + private void genNewMultiArray(int cpi) { + JavaType type = lookupType(cpi, MULTIANEWARRAY); + int rank = stream().readUByte(bci() + 3); + ValueNode[] dims = new ValueNode[rank]; + for (int i = rank - 1; i >= 0; i--) { + dims[i] = frameState.ipop(); + } + if (type instanceof ResolvedJavaType) { + frameState.apush(append(new NewMultiArrayNode((ResolvedJavaType) type, dims))); + } else { + handleUnresolvedNewMultiArray(type, dims); + } + } - private void genNewMultiArray(int cpi) { - JavaType type = lookupType(cpi, MULTIANEWARRAY); - int rank = stream().readUByte(bci() + 3); - ValueNode[] dims = new ValueNode[rank]; - for (int i = rank - 1; i >= 0; i--) { - dims[i] = frameState.ipop(); - } - if (type instanceof ResolvedJavaType) { - frameState.apush(append(new NewMultiArrayNode((ResolvedJavaType) type, dims))); - } else { - handleUnresolvedNewMultiArray(type, dims); - } - } + private void genGetField(JavaField field) { + emitExplicitExceptions(frameState.peek(0), null); - private void genGetField(JavaField field) { - emitExplicitExceptions(frameState.peek(0), null); - - Kind kind = field.getKind(); - ValueNode receiver = frameState.apop(); - if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { - appendOptimizedLoadField(kind, new LoadFieldNode(receiver, (ResolvedJavaField) field)); - } else { - handleUnresolvedLoadField(field, receiver); + Kind kind = field.getKind(); + ValueNode receiver = frameState.apop(); + if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { + appendOptimizedLoadField(kind, new LoadFieldNode(receiver, (ResolvedJavaField) field)); + } else { + handleUnresolvedLoadField(field, receiver); + } } - } + + public static class ExceptionInfo { - public static class ExceptionInfo { + public final FixedWithNextNode exceptionEdge; + public final ValueNode exception; - public final FixedWithNextNode exceptionEdge; - public final ValueNode exception; + public ExceptionInfo(FixedWithNextNode exceptionEdge, ValueNode exception) { + this.exceptionEdge = exceptionEdge; + this.exception = exception; + } + } - public ExceptionInfo(FixedWithNextNode exceptionEdge, ValueNode exception) { - this.exceptionEdge = exceptionEdge; - this.exception = exception; - } - } + private void emitNullCheck(ValueNode receiver) { + if (ObjectStamp.isObjectNonNull(receiver.stamp())) { + return; + } + BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); + BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this)); + append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.01)); + lastInstr = falseSucc; - private void emitNullCheck(ValueNode receiver) { - if (ObjectStamp.isObjectNonNull(receiver.stamp())) { - return; + if (OmitHotExceptionStacktrace.getValue()) { + ValueNode exception = ConstantNode.forObject(cachedNullPointerException, metaAccess, currentGraph); + trueSucc.setNext(handleException(exception, bci())); + } else { + DeferredForeignCallNode call = currentGraph.add(new DeferredForeignCallNode(CREATE_NULL_POINTER_EXCEPTION)); + call.setStateAfter(frameState.create(bci())); + trueSucc.setNext(call); + call.setNext(handleException(call, bci())); + } } - BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); - BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this)); - append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.01)); - lastInstr = falseSucc; - if (OmitHotExceptionStacktrace.getValue()) { - ValueNode exception = ConstantNode.forObject(cachedNullPointerException, metaAccess, currentGraph); - trueSucc.setNext(handleException(exception, bci())); - } else { - DeferredForeignCallNode call = currentGraph.add(new DeferredForeignCallNode(CREATE_NULL_POINTER_EXCEPTION)); - call.setStateAfter(frameState.create(bci())); - trueSucc.setNext(call); - call.setNext(handleException(call, bci())); + private static final ArrayIndexOutOfBoundsException cachedArrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException(); + private static final NullPointerException cachedNullPointerException = new NullPointerException(); + static { + cachedArrayIndexOutOfBoundsException.setStackTrace(new StackTraceElement[0]); + cachedNullPointerException.setStackTrace(new StackTraceElement[0]); } - } + + private void emitBoundsCheck(ValueNode index, ValueNode length) { + BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); + BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this)); + append(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.99)); + lastInstr = trueSucc; - private static final ArrayIndexOutOfBoundsException cachedArrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException(); - private static final NullPointerException cachedNullPointerException = new NullPointerException(); - static { - cachedArrayIndexOutOfBoundsException.setStackTrace(new StackTraceElement[0]); - cachedNullPointerException.setStackTrace(new StackTraceElement[0]); - } - - private void emitBoundsCheck(ValueNode index, ValueNode length) { - BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); - BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this)); - append(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.99)); - lastInstr = trueSucc; + if (OmitHotExceptionStacktrace.getValue()) { + ValueNode exception = ConstantNode.forObject(cachedArrayIndexOutOfBoundsException, metaAccess, currentGraph); + falseSucc.setNext(handleException(exception, bci())); + } else { + DeferredForeignCallNode call = currentGraph.add(new DeferredForeignCallNode(CREATE_OUT_OF_BOUNDS_EXCEPTION, index)); + call.setStateAfter(frameState.create(bci())); + falseSucc.setNext(call); + call.setNext(handleException(call, bci())); + } + } - if (OmitHotExceptionStacktrace.getValue()) { - ValueNode exception = ConstantNode.forObject(cachedArrayIndexOutOfBoundsException, metaAccess, currentGraph); - falseSucc.setNext(handleException(exception, bci())); - } else { - DeferredForeignCallNode call = currentGraph.add(new DeferredForeignCallNode(CREATE_OUT_OF_BOUNDS_EXCEPTION, index)); - call.setStateAfter(frameState.create(bci())); - falseSucc.setNext(call); - call.setNext(handleException(call, bci())); - } - } + protected void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) { + assert receiver != null; + if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { + return; + } - protected void emitExplicitExceptions(ValueNode receiver, ValueNode outOfBoundsIndex) { - assert receiver != null; - if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { - return; + emitNullCheck(receiver); + if (outOfBoundsIndex != null) { + ValueNode length = append(new ArrayLengthNode(receiver)); + emitBoundsCheck(outOfBoundsIndex, length); + } + Debug.metric("ExplicitExceptions").increment(); } - emitNullCheck(receiver); - if (outOfBoundsIndex != null) { - ValueNode length = append(new ArrayLengthNode(receiver)); - emitBoundsCheck(outOfBoundsIndex, length); - } - Debug.metric("ExplicitExceptions").increment(); - } - - private void genPutField(JavaField field) { - emitExplicitExceptions(frameState.peek(1), null); - - ValueNode value = frameState.pop(field.getKind().getStackKind()); - ValueNode receiver = frameState.apop(); - if (field instanceof ResolvedJavaField && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { - appendOptimizedStoreField(new StoreFieldNode(receiver, (ResolvedJavaField) field, value)); - } else { - handleUnresolvedStoreField(field, value, receiver); - } - } + private void genPutField(JavaField field) { + emitExplicitExceptions(frameState.peek(1), null); - private void genGetStatic(JavaField field) { - Kind kind = field.getKind(); - if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - appendOptimizedLoadField(kind, new LoadFieldNode(null, (ResolvedJavaField) field)); - } else { - handleUnresolvedLoadField(field, null); + ValueNode value = frameState.pop(field.getKind().getStackKind()); + ValueNode receiver = frameState.apop(); + if (field instanceof ResolvedJavaField && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { + appendOptimizedStoreField(new StoreFieldNode(receiver, (ResolvedJavaField) field, value)); + } else { + handleUnresolvedStoreField(field, value, receiver); + } } - } - - private void genPutStatic(JavaField field) { - ValueNode value = frameState.pop(field.getKind().getStackKind()); - if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - appendOptimizedStoreField(new StoreFieldNode(null, (ResolvedJavaField) field, value)); - } else { - handleUnresolvedStoreField(field, value, null); - } - } - - private ConstantNode genTypeOrDeopt(Representation representation, JavaType type, boolean initialized) { - if (initialized) { - return appendConstant(((ResolvedJavaType) type).getEncoding(representation)); - } else { - handleUnresolvedExceptionType(representation, type); - return null; - } - } - - private void appendOptimizedStoreField(StoreFieldNode store) { - append(store); - } - private void appendOptimizedLoadField(Kind kind, LoadFieldNode load) { - // append the load to the instruction - ValueNode optimized = append(load); - frameState.push(kind.getStackKind(), optimized); - } - - private void genInvokeStatic(JavaMethod target) { - if (target instanceof ResolvedJavaMethod) { - ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target; - ResolvedJavaType holder = resolvedTarget.getDeclaringClass(); - if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue()) { - handleUnresolvedInvoke(target, InvokeKind.Static); + private void genGetStatic(JavaField field) { + Kind kind = field.getKind(); + if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { + appendOptimizedLoadField(kind, new LoadFieldNode(null, (ResolvedJavaField) field)); } else { - ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterSlots(false), resolvedTarget.getSignature().getParameterCount(false)); - appendInvoke(InvokeKind.Static, resolvedTarget, args); + handleUnresolvedLoadField(field, null); } - } else { - handleUnresolvedInvoke(target, InvokeKind.Static); } - } - - private void genInvokeInterface(JavaMethod target) { - if (target instanceof ResolvedJavaMethod) { - ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); - genInvokeIndirect(InvokeKind.Interface, (ResolvedJavaMethod) target, args); - } else { - handleUnresolvedInvoke(target, InvokeKind.Interface); - } - } - private void genInvokeDynamic(JavaMethod target) { - if (target instanceof ResolvedJavaMethod) { - Object appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC); - if (appendix != null) { - frameState.apush(ConstantNode.forObject(appendix, metaAccess, currentGraph)); + private void genPutStatic(JavaField field) { + ValueNode value = frameState.pop(field.getKind().getStackKind()); + if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { + appendOptimizedStoreField(new StoreFieldNode(null, (ResolvedJavaField) field, value)); + } else { + handleUnresolvedStoreField(field, value, null); } - ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(false), target.getSignature().getParameterCount(false)); - appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args); - } else { - handleUnresolvedInvoke(target, InvokeKind.Static); } - } - private void genInvokeVirtual(JavaMethod target) { - if (target instanceof ResolvedJavaMethod) { - // Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...) - // or MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see - // https://wikis.oracle.com/display/HotSpotInternals/Method+handles+and+invokedynamic - boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers()); - Object appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL); - if (appendix != null) { - frameState.apush(ConstantNode.forObject(appendix, metaAccess, currentGraph)); + private ConstantNode genTypeOrDeopt(Representation representation, JavaType type, boolean initialized) { + if (initialized) { + return appendConstant(((ResolvedJavaType) type).getEncoding(representation)); + } else { + handleUnresolvedExceptionType(representation, type); + return null; } - ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(hasReceiver), target.getSignature().getParameterCount(hasReceiver)); - if (hasReceiver) { - genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); - } else { - appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args); - } - } else { - handleUnresolvedInvoke(target, InvokeKind.Virtual); } - } + private void appendOptimizedStoreField(StoreFieldNode store) { + append(store); + } - private void genInvokeSpecial(JavaMethod target) { - if (target instanceof ResolvedJavaMethod) { - assert target != null; - assert target.getSignature() != null; - ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); - invokeDirect((ResolvedJavaMethod) target, args); - } else { - handleUnresolvedInvoke(target, InvokeKind.Special); + private void appendOptimizedLoadField(Kind kind, LoadFieldNode load) { + // append the load to the instruction + ValueNode optimized = append(load); + frameState.push(kind.getStackKind(), optimized); } - } - private void genInvokeIndirect(InvokeKind invokeKind, ResolvedJavaMethod target, ValueNode[] args) { - ValueNode receiver = args[0]; - // attempt to devirtualize the call - ResolvedJavaType klass = target.getDeclaringClass(); - - // 0. check for trivial cases - if (target.canBeStaticallyBound()) { - // check for trivial cases (e.g. final methods, nonvirtual methods) - invokeDirect(target, args); - return; - } - // 1. check if the exact type of the receiver can be determined - ResolvedJavaType exact = klass.asExactType(); - if (exact == null && receiver.stamp() instanceof ObjectStamp) { - ObjectStamp receiverStamp = (ObjectStamp) receiver.stamp(); - if (receiverStamp.isExactType()) { - exact = receiverStamp.type(); + private void genInvokeStatic(JavaMethod target) { + if (target instanceof ResolvedJavaMethod) { + ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target; + ResolvedJavaType holder = resolvedTarget.getDeclaringClass(); + if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue()) { + handleUnresolvedInvoke(target, InvokeKind.Static); + } else { + ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterSlots(false), resolvedTarget.getSignature().getParameterCount(false)); + appendInvoke(InvokeKind.Static, resolvedTarget, args); + } + } else { + handleUnresolvedInvoke(target, InvokeKind.Static); } } - if (exact != null) { - // either the holder class is exact, or the receiver object has an exact type - ResolvedJavaMethod exactMethod = exact.resolveMethod(target); - if (exactMethod != null) { - invokeDirect(exactMethod, args); - return; + + private void genInvokeInterface(JavaMethod target) { + if (target instanceof ResolvedJavaMethod) { + ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); + genInvokeIndirect(InvokeKind.Interface, (ResolvedJavaMethod) target, args); + } else { + handleUnresolvedInvoke(target, InvokeKind.Interface); + } + } + + private void genInvokeDynamic(JavaMethod target) { + if (target instanceof ResolvedJavaMethod) { + Object appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC); + if (appendix != null) { + frameState.apush(ConstantNode.forObject(appendix, metaAccess, currentGraph)); + } + ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(false), target.getSignature().getParameterCount(false)); + appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args); + } else { + handleUnresolvedInvoke(target, InvokeKind.Static); } } - // devirtualization failed, produce an actual invokevirtual - appendInvoke(invokeKind, target, args); - } - private void invokeDirect(ResolvedJavaMethod target, ValueNode[] args) { - appendInvoke(InvokeKind.Special, target, args); - } + private void genInvokeVirtual(JavaMethod target) { + if (target instanceof ResolvedJavaMethod) { + /* + * Special handling for runtimes that rewrite an invocation of + * MethodHandle.invoke(...) or MethodHandle.invokeExact(...) to a static adapter. + * HotSpot does this - see + * https://wikis.oracle.com/display/HotSpotInternals/Method+handles + * +and+invokedynamic + */ + boolean hasReceiver = !isStatic(((ResolvedJavaMethod) target).getModifiers()); + Object appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL); + if (appendix != null) { + frameState.apush(ConstantNode.forObject(appendix, metaAccess, currentGraph)); + } + ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(hasReceiver), target.getSignature().getParameterCount(hasReceiver)); + if (hasReceiver) { + genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); + } else { + appendInvoke(InvokeKind.Static, (ResolvedJavaMethod) target, args); + } + } else { + handleUnresolvedInvoke(target, InvokeKind.Virtual); + } - private void appendInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) { - Kind resultType = targetMethod.getSignature().getReturnKind(); - if (DeoptALot.getValue()) { - append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint)); - frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph)); - return; } - JavaType returnType = targetMethod.getSignature().getReturnType(method.getDeclaringClass()); - if (graphBuilderConfig.eagerResolving()) { - returnType = returnType.resolve(targetMethod.getDeclaringClass()); - } - if (invokeKind != InvokeKind.Static) { - emitExplicitExceptions(args[0], null); - if (invokeKind != InvokeKind.Special && this.optimisticOpts.useTypeCheckHints()) { - JavaTypeProfile profile = profilingInfo.getTypeProfile(bci()); - args[0] = TypeProfileProxyNode.create(args[0], profile); + private void genInvokeSpecial(JavaMethod target) { + if (target instanceof ResolvedJavaMethod) { + assert target != null; + assert target.getSignature() != null; + ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); + invokeDirect((ResolvedJavaMethod) target, args); + } else { + handleUnresolvedInvoke(target, InvokeKind.Special); } } - MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType)); - // be conservative if information was not recorded (could result in endless recompiles - // otherwise) - if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { - createInvoke(callTarget, resultType); - } else { - assert bci() == currentBlock.endBci; - frameState.clearNonLiveLocals(currentBlock.localsLiveOut); - - InvokeWithExceptionNode invoke = createInvokeWithException(callTarget, resultType); - - Block nextBlock = currentBlock.successors.get(0); - invoke.setNext(createTarget(nextBlock, frameState)); - } - } - - protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType) { - return new MethodCallTargetNode(invokeKind, targetMethod, args, returnType); - } - - protected InvokeNode createInvoke(CallTargetNode callTarget, Kind resultType) { - InvokeNode invoke = append(new InvokeNode(callTarget, bci())); - frameState.pushReturn(resultType, invoke); - return invoke; - } + private void genInvokeIndirect(InvokeKind invokeKind, ResolvedJavaMethod target, ValueNode[] args) { + ValueNode receiver = args[0]; + // attempt to devirtualize the call + ResolvedJavaType klass = target.getDeclaringClass(); - protected InvokeWithExceptionNode createInvokeWithException(CallTargetNode callTarget, Kind resultType) { - DispatchBeginNode exceptionEdge = handleException(null, bci()); - InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci())); - frameState.pushReturn(resultType, invoke); - Block nextBlock = currentBlock.successors.get(0); - invoke.setStateAfter(frameState.create(nextBlock.startBci)); - return invoke; - } - - private void genReturn(ValueNode x) { - frameState.clearStack(); - if (x != null) { - frameState.push(x.kind(), x); + // 0. check for trivial cases + if (target.canBeStaticallyBound()) { + // check for trivial cases (e.g. final methods, nonvirtual methods) + invokeDirect(target, args); + return; + } + // 1. check if the exact type of the receiver can be determined + ResolvedJavaType exact = klass.asExactType(); + if (exact == null && receiver.stamp() instanceof ObjectStamp) { + ObjectStamp receiverStamp = (ObjectStamp) receiver.stamp(); + if (receiverStamp.isExactType()) { + exact = receiverStamp.type(); + } + } + if (exact != null) { + // either the holder class is exact, or the receiver object has an exact type + ResolvedJavaMethod exactMethod = exact.resolveMethod(target); + if (exactMethod != null) { + invokeDirect(exactMethod, args); + return; + } + } + // devirtualization failed, produce an actual invokevirtual + appendInvoke(invokeKind, target, args); } - appendGoto(createTarget(returnBlock(bci()), frameState)); - } - private MonitorEnterNode genMonitorEnter(ValueNode x) { - MonitorIdNode monitorId = currentGraph.add(new MonitorIdNode(frameState.lockDepth())); - MonitorEnterNode monitorEnter = append(new MonitorEnterNode(x, monitorId)); - frameState.pushLock(x, monitorId); - return monitorEnter; - } - - private MonitorExitNode genMonitorExit(ValueNode x, ValueNode returnValue) { - MonitorIdNode monitorId = frameState.peekMonitorId(); - ValueNode lockedObject = frameState.popLock(); - if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { - throw new BailoutException("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)); - } - MonitorExitNode monitorExit = append(new MonitorExitNode(x, monitorId, returnValue)); - return monitorExit; - } - - private void genJsr(int dest) { - Block successor = currentBlock.jsrSuccessor; - assert successor.startBci == dest : successor.startBci + " != " + dest + " @" + bci(); - JsrScope scope = currentBlock.jsrScope; - if (!successor.jsrScope.pop().equals(scope)) { - throw new JsrNotSupportedBailout("unstructured control flow (internal limitation)"); + private void invokeDirect(ResolvedJavaMethod target, ValueNode[] args) { + appendInvoke(InvokeKind.Special, target, args); } - if (successor.jsrScope.nextReturnAddress() != stream().nextBCI()) { - throw new JsrNotSupportedBailout("unstructured control flow (internal limitation)"); - } - frameState.push(Kind.Int, ConstantNode.forInt(stream().nextBCI(), currentGraph)); - appendGoto(createTarget(successor, frameState)); - } - private void genRet(int localIndex) { - Block successor = currentBlock.retSuccessor; - ValueNode local = frameState.loadLocal(localIndex); - JsrScope scope = currentBlock.jsrScope; - int retAddress = scope.nextReturnAddress(); - append(new FixedGuardNode(currentGraph.unique(new IntegerEqualsNode(local, ConstantNode.forInt(retAddress, currentGraph))), JavaSubroutineMismatch, InvalidateReprofile)); - if (!successor.jsrScope.equals(scope.pop())) { - throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)"); - } - appendGoto(createTarget(successor, frameState)); - } - - private double[] switchProbability(int numberOfCases, int bci) { - double[] prob = profilingInfo.getSwitchProbabilities(bci); - if (prob != null) { - assert prob.length == numberOfCases; - } else { - Debug.log("Missing probability (switch) in %s at bci %d", method, bci); - prob = new double[numberOfCases]; - for (int i = 0; i < numberOfCases; i++) { - prob[i] = 1.0d / numberOfCases; + private void appendInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) { + Kind resultType = targetMethod.getSignature().getReturnKind(); + if (DeoptALot.getValue()) { + append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint)); + frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph)); + return; } - } - assert allPositive(prob); - return prob; - } - private static boolean allPositive(double[] a) { - for (double d : a) { - if (d < 0) { - return false; + JavaType returnType = targetMethod.getSignature().getReturnType(method.getDeclaringClass()); + if (graphBuilderConfig.eagerResolving()) { + returnType = returnType.resolve(targetMethod.getDeclaringClass()); } - } - return true; - } + if (invokeKind != InvokeKind.Static) { + emitExplicitExceptions(args[0], null); + if (invokeKind != InvokeKind.Special && this.optimisticOpts.useTypeCheckHints()) { + JavaTypeProfile profile = profilingInfo.getTypeProfile(bci()); + args[0] = TypeProfileProxyNode.create(args[0], profile); + } + } + MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType)); - /** - * Helper function that sums up the probabilities of all keys that lead to a specific successor. - * - * @return an array of size successorCount with the accumulated probability for each successor. - */ - private static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) { - double[] probability = new double[successorCount]; - for (int i = 0; i < keySuccessors.length; i++) { - probability[keySuccessors[i]] += keyProbabilities[i]; - } - return probability; - } + // be conservative if information was not recorded (could result in endless recompiles + // otherwise) + if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { + createInvoke(callTarget, resultType); + } else { + assert bci() == currentBlock.endBci; + frameState.clearNonLiveLocals(currentBlock.localsLiveOut); - private void genSwitch(BytecodeSwitch bs) { - int bci = bci(); - ValueNode value = frameState.ipop(); + InvokeWithExceptionNode invoke = createInvokeWithException(callTarget, resultType); - int nofCases = bs.numberOfCases(); - double[] keyProbabilities = switchProbability(nofCases + 1, bci); - - Map bciToBlockSuccessorIndex = new HashMap<>(); - for (int i = 0; i < currentBlock.successors.size(); i++) { - assert !bciToBlockSuccessorIndex.containsKey(currentBlock.successors.get(i).startBci); - if (!bciToBlockSuccessorIndex.containsKey(currentBlock.successors.get(i).startBci)) { - bciToBlockSuccessorIndex.put(currentBlock.successors.get(i).startBci, new SuccessorInfo(i)); + Block nextBlock = currentBlock.successors.get(0); + invoke.setNext(createTarget(nextBlock, frameState)); } } - ArrayList actualSuccessors = new ArrayList<>(); - int[] keys = new int[nofCases]; - int[] keySuccessors = new int[nofCases + 1]; - int deoptSuccessorIndex = -1; - int nextSuccessorIndex = 0; - for (int i = 0; i < nofCases + 1; i++) { - if (i < nofCases) { - keys[i] = bs.keyAt(i); + protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType) { + return new MethodCallTargetNode(invokeKind, targetMethod, args, returnType); + } + + protected InvokeNode createInvoke(CallTargetNode callTarget, Kind resultType) { + InvokeNode invoke = append(new InvokeNode(callTarget, bci())); + frameState.pushReturn(resultType, invoke); + return invoke; + } + + protected InvokeWithExceptionNode createInvokeWithException(CallTargetNode callTarget, Kind resultType) { + DispatchBeginNode exceptionEdge = handleException(null, bci()); + InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci())); + frameState.pushReturn(resultType, invoke); + Block nextBlock = currentBlock.successors.get(0); + invoke.setStateAfter(frameState.create(nextBlock.startBci)); + return invoke; + } + + private void genReturn(ValueNode x) { + frameState.clearStack(); + if (x != null) { + frameState.push(x.kind(), x); + } + appendGoto(createTarget(returnBlock(bci()), frameState)); + } + + private MonitorEnterNode genMonitorEnter(ValueNode x) { + MonitorIdNode monitorId = currentGraph.add(new MonitorIdNode(frameState.lockDepth())); + MonitorEnterNode monitorEnter = append(new MonitorEnterNode(x, monitorId)); + frameState.pushLock(x, monitorId); + return monitorEnter; + } + + private MonitorExitNode genMonitorExit(ValueNode x, ValueNode returnValue) { + MonitorIdNode monitorId = frameState.peekMonitorId(); + ValueNode lockedObject = frameState.popLock(); + if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { + throw new BailoutException("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject)); + } + MonitorExitNode monitorExit = append(new MonitorExitNode(x, monitorId, returnValue)); + return monitorExit; + } + + private void genJsr(int dest) { + Block successor = currentBlock.jsrSuccessor; + assert successor.startBci == dest : successor.startBci + " != " + dest + " @" + bci(); + JsrScope scope = currentBlock.jsrScope; + if (!successor.jsrScope.pop().equals(scope)) { + throw new JsrNotSupportedBailout("unstructured control flow (internal limitation)"); + } + if (successor.jsrScope.nextReturnAddress() != stream().nextBCI()) { + throw new JsrNotSupportedBailout("unstructured control flow (internal limitation)"); + } + frameState.push(Kind.Int, ConstantNode.forInt(stream().nextBCI(), currentGraph)); + appendGoto(createTarget(successor, frameState)); + } + + private void genRet(int localIndex) { + Block successor = currentBlock.retSuccessor; + ValueNode local = frameState.loadLocal(localIndex); + JsrScope scope = currentBlock.jsrScope; + int retAddress = scope.nextReturnAddress(); + append(new FixedGuardNode(currentGraph.unique(new IntegerEqualsNode(local, ConstantNode.forInt(retAddress, currentGraph))), JavaSubroutineMismatch, InvalidateReprofile)); + if (!successor.jsrScope.equals(scope.pop())) { + throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)"); + } + appendGoto(createTarget(successor, frameState)); + } + + private double[] switchProbability(int numberOfCases, int bci) { + double[] prob = profilingInfo.getSwitchProbabilities(bci); + if (prob != null) { + assert prob.length == numberOfCases; + } else { + Debug.log("Missing probability (switch) in %s at bci %d", method, bci); + prob = new double[numberOfCases]; + for (int i = 0; i < numberOfCases; i++) { + prob[i] = 1.0d / numberOfCases; + } + } + assert allPositive(prob); + return prob; + } + + private static boolean allPositive(double[] a) { + for (double d : a) { + if (d < 0) { + return false; + } + } + return true; + } + + /** + * Helper function that sums up the probabilities of all keys that lead to a specific + * successor. + * + * @return an array of size successorCount with the accumulated probability for each + * successor. + */ + private static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) { + double[] probability = new double[successorCount]; + for (int i = 0; i < keySuccessors.length; i++) { + probability[keySuccessors[i]] += keyProbabilities[i]; + } + return probability; + } + + private void genSwitch(BytecodeSwitch bs) { + int bci = bci(); + ValueNode value = frameState.ipop(); + + int nofCases = bs.numberOfCases(); + double[] keyProbabilities = switchProbability(nofCases + 1, bci); + + Map bciToBlockSuccessorIndex = new HashMap<>(); + for (int i = 0; i < currentBlock.successors.size(); i++) { + assert !bciToBlockSuccessorIndex.containsKey(currentBlock.successors.get(i).startBci); + if (!bciToBlockSuccessorIndex.containsKey(currentBlock.successors.get(i).startBci)) { + bciToBlockSuccessorIndex.put(currentBlock.successors.get(i).startBci, new SuccessorInfo(i)); + } } - if (isNeverExecutedCode(keyProbabilities[i])) { - if (deoptSuccessorIndex < 0) { - deoptSuccessorIndex = nextSuccessorIndex++; - actualSuccessors.add(null); + ArrayList actualSuccessors = new ArrayList<>(); + int[] keys = new int[nofCases]; + int[] keySuccessors = new int[nofCases + 1]; + int deoptSuccessorIndex = -1; + int nextSuccessorIndex = 0; + for (int i = 0; i < nofCases + 1; i++) { + if (i < nofCases) { + keys[i] = bs.keyAt(i); } - keySuccessors[i] = deoptSuccessorIndex; - } else { - int targetBci = i >= nofCases ? bs.defaultTarget() : bs.targetAt(i); - SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci); - if (info.actualIndex < 0) { - info.actualIndex = nextSuccessorIndex++; - actualSuccessors.add(currentBlock.successors.get(info.blockIndex)); + + if (isNeverExecutedCode(keyProbabilities[i])) { + if (deoptSuccessorIndex < 0) { + deoptSuccessorIndex = nextSuccessorIndex++; + actualSuccessors.add(null); + } + keySuccessors[i] = deoptSuccessorIndex; + } else { + int targetBci = i >= nofCases ? bs.defaultTarget() : bs.targetAt(i); + SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci); + if (info.actualIndex < 0) { + info.actualIndex = nextSuccessorIndex++; + actualSuccessors.add(currentBlock.successors.get(info.blockIndex)); + } + keySuccessors[i] = info.actualIndex; } - keySuccessors[i] = info.actualIndex; + } + + double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities); + IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors)); + for (int i = 0; i < actualSuccessors.size(); i++) { + switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState)); + } + + } + + private static class SuccessorInfo { + + int blockIndex; + int actualIndex; + + public SuccessorInfo(int blockSuccessorIndex) { + this.blockIndex = blockSuccessorIndex; + actualIndex = -1; } } - double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities); - IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors)); - for (int i = 0; i < actualSuccessors.size(); i++) { - switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState)); + protected ConstantNode appendConstant(Constant constant) { + assert constant != null; + return ConstantNode.forConstant(constant, metaAccess, currentGraph); + } + + private T append(T fixed) { + assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; + assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; + T added = currentGraph.add(fixed); + lastInstr.setNext(added); + lastInstr = null; + return added; + } + + private T append(T fixed) { + assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; + assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; + T added = currentGraph.add(fixed); + lastInstr.setNext(added); + lastInstr = null; + return added; + } + + protected T append(T fixed) { + assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; + assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; + T added = currentGraph.add(fixed); + lastInstr.setNext(added); + lastInstr = added; + return added; + } + + private T append(T v) { + assert !(v instanceof ConstantNode); + T added = currentGraph.unique(v); + return added; + } + + private static class Target { + + FixedNode fixed; + FrameStateBuilder state; + + public Target(FixedNode fixed, FrameStateBuilder state) { + this.fixed = fixed; + this.state = state; + } } - } - - private static class SuccessorInfo { - - int blockIndex; - int actualIndex; - - public SuccessorInfo(int blockSuccessorIndex) { - this.blockIndex = blockSuccessorIndex; - actualIndex = -1; - } - } - - protected ConstantNode appendConstant(Constant constant) { - assert constant != null; - return ConstantNode.forConstant(constant, metaAccess, currentGraph); - } + private Target checkLoopExit(FixedNode target, Block targetBlock, FrameStateBuilder state) { + if (currentBlock != null) { + long exits = currentBlock.loops & ~targetBlock.loops; + if (exits != 0) { + LoopExitNode firstLoopExit = null; + LoopExitNode lastLoopExit = null; - private T append(T fixed) { - assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; - assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; - T added = currentGraph.add(fixed); - lastInstr.setNext(added); - lastInstr = null; - return added; - } + int pos = 0; + ArrayList exitLoops = new ArrayList<>(Long.bitCount(exits)); + do { + long lMask = 1L << pos; + if ((exits & lMask) != 0) { + exitLoops.add(loopHeaders[pos]); + exits &= ~lMask; + } + pos++; + } while (exits != 0); - private T append(T fixed) { - assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; - assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; - T added = currentGraph.add(fixed); - lastInstr.setNext(added); - lastInstr = null; - return added; - } + Collections.sort(exitLoops, new Comparator() { - protected T append(T fixed) { - assert !fixed.isAlive() && !fixed.isDeleted() : "instruction should not have been appended yet"; - assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; - T added = currentGraph.add(fixed); - lastInstr.setNext(added); - lastInstr = added; - return added; - } - - private T append(T v) { - assert !(v instanceof ConstantNode); - T added = currentGraph.unique(v); - return added; - } - - private static class Target { + @Override + public int compare(Block o1, Block o2) { + return Long.bitCount(o2.loops) - Long.bitCount(o1.loops); + } + }); - FixedNode fixed; - FrameStateBuilder state; - - public Target(FixedNode fixed, FrameStateBuilder state) { - this.fixed = fixed; - this.state = state; - } - } - - private Target checkLoopExit(FixedNode target, Block targetBlock, FrameStateBuilder state) { - if (currentBlock != null) { - long exits = currentBlock.loops & ~targetBlock.loops; - if (exits != 0) { - LoopExitNode firstLoopExit = null; - LoopExitNode lastLoopExit = null; - - int pos = 0; - ArrayList exitLoops = new ArrayList<>(Long.bitCount(exits)); - do { - long lMask = 1L << pos; - if ((exits & lMask) != 0) { - exitLoops.add(loopHeaders[pos]); - exits &= ~lMask; + int bci = targetBlock.startBci; + if (targetBlock instanceof ExceptionDispatchBlock) { + bci = ((ExceptionDispatchBlock) targetBlock).deoptBci; } - pos++; - } while (exits != 0); - - Collections.sort(exitLoops, new Comparator() { + FrameStateBuilder newState = state.copy(); + for (Block loop : exitLoops) { + LoopBeginNode loopBegin = (LoopBeginNode) loop.firstInstruction; + LoopExitNode loopExit = currentGraph.add(new LoopExitNode(loopBegin)); + if (lastLoopExit != null) { + lastLoopExit.setNext(loopExit); + } + if (firstLoopExit == null) { + firstLoopExit = loopExit; + } + lastLoopExit = loopExit; + Debug.log("Target %s (%s) Exits %s, scanning framestates...", targetBlock, target, loop); + newState.insertLoopProxies(loopExit, loop.entryState); + loopExit.setStateAfter(newState.create(bci)); + } - @Override - public int compare(Block o1, Block o2) { - return Long.bitCount(o2.loops) - Long.bitCount(o1.loops); - } - }); - - int bci = targetBlock.startBci; - if (targetBlock instanceof ExceptionDispatchBlock) { - bci = ((ExceptionDispatchBlock) targetBlock).deoptBci; + lastLoopExit.setNext(target); + return new Target(firstLoopExit, newState); } - FrameStateBuilder newState = state.copy(); - for (Block loop : exitLoops) { - LoopBeginNode loopBegin = (LoopBeginNode) loop.firstInstruction; - LoopExitNode loopExit = currentGraph.add(new LoopExitNode(loopBegin)); - if (lastLoopExit != null) { - lastLoopExit.setNext(loopExit); - } - if (firstLoopExit == null) { - firstLoopExit = loopExit; - } - lastLoopExit = loopExit; - Debug.log("Target %s (%s) Exits %s, scanning framestates...", targetBlock, target, loop); - newState.insertLoopProxies(loopExit, loop.entryState); - loopExit.setStateAfter(newState.create(bci)); - } + } + return new Target(target, state); + } - lastLoopExit.setNext(target); - return new Target(firstLoopExit, newState); + private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) { + assert probability >= 0 && probability <= 1.01 : probability; + if (isNeverExecutedCode(probability)) { + return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); + } else { + assert block != null; + return createTarget(block, stateAfter); } } - return new Target(target, state); - } + + private boolean isNeverExecutedCode(double probability) { + return probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI; + } + + private FixedNode createTarget(Block block, FrameStateBuilder state) { + assert block != null && state != null; + assert !block.isExceptionEntry || state.stackSize() == 1; - private FixedNode createTarget(double probability, Block block, FrameStateBuilder stateAfter) { - assert probability >= 0 && probability <= 1.01 : probability; - if (isNeverExecutedCode(probability)) { - return currentGraph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); - } else { - assert block != null; - return createTarget(block, stateAfter); - } - } + if (block.firstInstruction == null) { + /* + * This is the first time we see this block as a branch target. Create and return a + * placeholder that later can be replaced with a MergeNode when we see this block + * again. + */ + block.firstInstruction = currentGraph.add(new BlockPlaceholderNode(this)); + Target target = checkLoopExit(block.firstInstruction, block, state); + FixedNode result = target.fixed; + block.entryState = target.state == state ? state.copy() : target.state; + block.entryState.clearNonLiveLocals(block.localsLiveIn); + + Debug.log("createTarget %s: first visit, result: %s", block, block.firstInstruction); + return result; + } + + // We already saw this block before, so we have to merge states. + if (!block.entryState.isCompatibleWith(state)) { + throw new BailoutException("stacks do not match; bytecodes would not verify"); + } - private boolean isNeverExecutedCode(double probability) { - return probability == 0 && optimisticOpts.removeNeverExecutedCode() && entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI; - } + if (block.firstInstruction instanceof LoopBeginNode) { + assert block.isLoopHeader && currentBlock.blockID >= block.blockID : "must be backward branch"; + /* + * Backward loop edge. We need to create a special LoopEndNode and merge with the + * loop begin node created before. + */ + LoopBeginNode loopBegin = (LoopBeginNode) block.firstInstruction; + Target target = checkLoopExit(currentGraph.add(new LoopEndNode(loopBegin)), block, state); + FixedNode result = target.fixed; + block.entryState.merge(loopBegin, target.state); - private FixedNode createTarget(Block block, FrameStateBuilder state) { - assert block != null && state != null; - assert !block.isExceptionEntry || state.stackSize() == 1; + Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); + return result; + } + assert currentBlock == null || currentBlock.blockID < block.blockID : "must not be backward branch"; + assert block.firstInstruction.next() == null : "bytecodes already parsed for block"; - if (block.firstInstruction == null) { - // This is the first time we see this block as a branch target. - // Create and return a placeholder that later can be replaced with a MergeNode when we - // see this block again. - block.firstInstruction = currentGraph.add(new BlockPlaceholderNode(this)); - Target target = checkLoopExit(block.firstInstruction, block, state); + if (block.firstInstruction instanceof BlockPlaceholderNode) { + /* + * This is the second time we see this block. Create the actual MergeNode and the + * End Node for the already existing edge. For simplicity, we leave the placeholder + * in the graph and just append the new nodes after the placeholder. + */ + BlockPlaceholderNode placeholder = (BlockPlaceholderNode) block.firstInstruction; + + // The EndNode for the already existing edge. + AbstractEndNode end = currentGraph.add(new EndNode()); + // The MergeNode that replaces the placeholder. + MergeNode mergeNode = currentGraph.add(new MergeNode()); + FixedNode next = placeholder.next(); + + placeholder.setNext(end); + mergeNode.addForwardEnd(end); + mergeNode.setNext(next); + + block.firstInstruction = mergeNode; + } + + MergeNode mergeNode = (MergeNode) block.firstInstruction; + + // The EndNode for the newly merged edge. + AbstractEndNode newEnd = currentGraph.add(new EndNode()); + Target target = checkLoopExit(newEnd, block, state); FixedNode result = target.fixed; - block.entryState = target.state == state ? state.copy() : target.state; - block.entryState.clearNonLiveLocals(block.localsLiveIn); + block.entryState.merge(mergeNode, target.state); + mergeNode.addForwardEnd(newEnd); - Debug.log("createTarget %s: first visit, result: %s", block, block.firstInstruction); + Debug.log("createTarget %s: merging state, result: %s", block, result); return result; } - // We already saw this block before, so we have to merge states. - if (!block.entryState.isCompatibleWith(state)) { - throw new BailoutException("stacks do not match; bytecodes would not verify"); + /** + * Returns a block begin node with the specified state. If the specified probability is 0, + * the block deoptimizes immediately. + */ + private AbstractBeginNode createBlockTarget(double probability, Block block, FrameStateBuilder stateAfter) { + FixedNode target = createTarget(probability, block, stateAfter); + AbstractBeginNode begin = AbstractBeginNode.begin(target); + + assert !(target instanceof DeoptimizeNode && begin.stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node, because we have to deoptimize " + + "to a bci _before_ the actual if, so that the interpreter can update the profiling information."; + return begin; } - if (block.firstInstruction instanceof LoopBeginNode) { - assert block.isLoopHeader && currentBlock.blockID >= block.blockID : "must be backward branch"; - // Backward loop edge. We need to create a special LoopEndNode and merge with the loop - // begin node created before. - LoopBeginNode loopBegin = (LoopBeginNode) block.firstInstruction; - Target target = checkLoopExit(currentGraph.add(new LoopEndNode(loopBegin)), block, state); - FixedNode result = target.fixed; - block.entryState.merge(loopBegin, target.state); - - Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); - return result; - } - assert currentBlock == null || currentBlock.blockID < block.blockID : "must not be backward branch"; - assert block.firstInstruction.next() == null : "bytecodes already parsed for block"; - - if (block.firstInstruction instanceof BlockPlaceholderNode) { - // This is the second time we see this block. Create the actual MergeNode and the End - // Node for the already existing edge. - // For simplicity, we leave the placeholder in the graph and just append the new nodes - // after the placeholder. - BlockPlaceholderNode placeholder = (BlockPlaceholderNode) block.firstInstruction; - - // The EndNode for the already existing edge. - AbstractEndNode end = currentGraph.add(new EndNode()); - // The MergeNode that replaces the placeholder. - MergeNode mergeNode = currentGraph.add(new MergeNode()); - FixedNode next = placeholder.next(); - - placeholder.setNext(end); - mergeNode.addForwardEnd(end); - mergeNode.setNext(next); - - block.firstInstruction = mergeNode; + private ValueNode synchronizedObject(FrameStateBuilder state, ResolvedJavaMethod target) { + if (isStatic(target.getModifiers())) { + return appendConstant(target.getDeclaringClass().getEncoding(Representation.JavaClass)); + } else { + return state.loadLocal(0); + } } - MergeNode mergeNode = (MergeNode) block.firstInstruction; - - // The EndNode for the newly merged edge. - AbstractEndNode newEnd = currentGraph.add(new EndNode()); - Target target = checkLoopExit(newEnd, block, state); - FixedNode result = target.fixed; - block.entryState.merge(mergeNode, target.state); - mergeNode.addForwardEnd(newEnd); - - Debug.log("createTarget %s: merging state, result: %s", block, result); - return result; - } + private void processBlock(Block block) { + // Ignore blocks that have no predecessors by the time their bytecodes are parsed + if (block == null || block.firstInstruction == null) { + Debug.log("Ignoring block %s", block); + return; + } + Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, block.firstInstruction, block.isLoopHeader); - /** - * Returns a block begin node with the specified state. If the specified probability is 0, the - * block deoptimizes immediately. - */ - private AbstractBeginNode createBlockTarget(double probability, Block block, FrameStateBuilder stateAfter) { - FixedNode target = createTarget(probability, block, stateAfter); - AbstractBeginNode begin = AbstractBeginNode.begin(target); - - assert !(target instanceof DeoptimizeNode && begin.stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node, because we have to deoptimize " - + "to a bci _before_ the actual if, so that the interpreter can update the profiling information."; - return begin; - } + lastInstr = block.firstInstruction; + frameState = block.entryState; + currentBlock = block; - private ValueNode synchronizedObject(FrameStateBuilder state, ResolvedJavaMethod target) { - if (isStatic(target.getModifiers())) { - return appendConstant(target.getDeclaringClass().getEncoding(Representation.JavaClass)); - } else { - return state.loadLocal(0); - } - } + frameState.cleanupDeletedPhis(); + if (lastInstr instanceof MergeNode) { + int bci = block.startBci; + if (block instanceof ExceptionDispatchBlock) { + bci = ((ExceptionDispatchBlock) block).deoptBci; + } + ((MergeNode) lastInstr).setStateAfter(frameState.create(bci)); + } - private void processBlock(Block block) { - // Ignore blocks that have no predecessors by the time their bytecodes are parsed - if (block == null || block.firstInstruction == null) { - Debug.log("Ignoring block %s", block); - return; - } - Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, block.firstInstruction, block.isLoopHeader); - - lastInstr = block.firstInstruction; - frameState = block.entryState; - currentBlock = block; - - frameState.cleanupDeletedPhis(); - if (lastInstr instanceof MergeNode) { - int bci = block.startBci; - if (block instanceof ExceptionDispatchBlock) { - bci = ((ExceptionDispatchBlock) block).deoptBci; + if (block == returnBlock) { + frameState.setRethrowException(false); + createReturn(); + } else if (block == unwindBlock) { + frameState.setRethrowException(false); + createUnwind(); + } else if (block instanceof ExceptionDispatchBlock) { + createExceptionDispatch((ExceptionDispatchBlock) block); + } else { + frameState.setRethrowException(false); + iterateBytecodesForBlock(block); } - ((MergeNode) lastInstr).setStateAfter(frameState.create(bci)); + indent.outdent(); } - if (block == returnBlock) { - frameState.setRethrowException(false); - createReturn(); - } else if (block == unwindBlock) { - frameState.setRethrowException(false); - createUnwind(); - } else if (block instanceof ExceptionDispatchBlock) { - createExceptionDispatch((ExceptionDispatchBlock) block); - } else { - frameState.setRethrowException(false); - iterateBytecodesForBlock(block); - } - indent.outdent(); - } - - private void connectLoopEndToBegin() { - for (LoopBeginNode begin : currentGraph.getNodes(LoopBeginNode.class)) { - if (begin.loopEnds().isEmpty()) { - // @formatter:off + private void connectLoopEndToBegin() { + for (LoopBeginNode begin : currentGraph.getNodes(LoopBeginNode.class)) { + if (begin.loopEnds().isEmpty()) { + // @formatter:off // Remove loop header without loop ends. // This can happen with degenerated loops like this one: // for (;;) { @@ -1642,207 +1676,210 @@ // } // } // @formatter:on - assert begin.forwardEndCount() == 1; - currentGraph.reduceDegenerateLoopBegin(begin); - } else { - GraphUtil.normalizeLoopBegin(begin); - } - } - } - - private void createUnwind() { - assert frameState.stackSize() == 1 : frameState; - ValueNode exception = frameState.apop(); - append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); - synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI, null); - append(new UnwindNode(exception)); - } - - private void createReturn() { - Kind returnKind = method.getSignature().getReturnKind().getStackKind(); - ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); - assert frameState.stackSize() == 0; - - if (graphBuilderConfig.eagerInfopointMode()) { - append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci()))); - } - - synchronizedEpilogue(FrameState.AFTER_BCI, x); - if (frameState.lockDepth() != 0) { - throw new BailoutException("unbalanced monitors"); - } - - append(new ReturnNode(x)); - } - - private void synchronizedEpilogue(int bci, ValueNode returnValue) { - if (Modifier.isSynchronized(method.getModifiers())) { - MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue); - monitorExit.setStateAfter(frameState.create(bci)); - assert !frameState.rethrowException(); - } - } - - private void createExceptionDispatch(ExceptionDispatchBlock block) { - assert frameState.stackSize() == 1 : frameState; - if (block.handler.isCatchAll()) { - assert block.successors.size() == 1; - appendGoto(createTarget(block.successors.get(0), frameState)); - return; - } - - JavaType catchType = block.handler.getCatchType(); - if (graphBuilderConfig.eagerResolving()) { - catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF); - } - boolean initialized = (catchType instanceof ResolvedJavaType); - if (initialized && graphBuilderConfig.getSkippedExceptionTypes() != null) { - ResolvedJavaType resolvedCatchType = (ResolvedJavaType) catchType; - for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) { - if (skippedType.isAssignableFrom(resolvedCatchType)) { - append(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); - return; + assert begin.forwardEndCount() == 1; + currentGraph.reduceDegenerateLoopBegin(begin); + } else { + GraphUtil.normalizeLoopBegin(begin); } } } - ConstantNode typeInstruction = genTypeOrDeopt(Representation.ObjectHub, catchType, initialized); - if (typeInstruction != null) { - Block nextBlock = block.successors.size() == 1 ? unwindBlock(block.deoptBci) : block.successors.get(1); - ValueNode exception = frameState.stackAt(0); - CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null, false)); - frameState.apop(); - frameState.push(Kind.Object, checkCast); - FixedNode catchSuccessor = createTarget(block.successors.get(0), frameState); - frameState.apop(); - frameState.push(Kind.Object, exception); - FixedNode nextDispatch = createTarget(nextBlock, frameState); - checkCast.setNext(catchSuccessor); - append(new IfNode(currentGraph.unique(new InstanceOfNode((ResolvedJavaType) catchType, exception, null)), checkCast, nextDispatch, 0.5)); + private void createUnwind() { + assert frameState.stackSize() == 1 : frameState; + ValueNode exception = frameState.apop(); + append(new FixedGuardNode(currentGraph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); + synchronizedEpilogue(FrameState.AFTER_EXCEPTION_BCI, null); + append(new UnwindNode(exception)); } - } + + private void createReturn() { + Kind returnKind = method.getSignature().getReturnKind().getStackKind(); + ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); + assert frameState.stackSize() == 0; - private void appendGoto(FixedNode target) { - if (lastInstr != null) { - lastInstr.setNext(target); + if (graphBuilderConfig.eagerInfopointMode()) { + append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(bci()))); + } + + synchronizedEpilogue(FrameState.AFTER_BCI, x); + if (frameState.lockDepth() != 0) { + throw new BailoutException("unbalanced monitors"); + } + + append(new ReturnNode(x)); } - } - - private static boolean isBlockEnd(Node n) { - return n instanceof ControlSplitNode || n instanceof ControlSinkNode; - } - private void iterateBytecodesForBlock(Block block) { - if (block.isLoopHeader) { - // Create the loop header block, which later will merge the backward branches of the - // loop. - AbstractEndNode preLoopEnd = currentGraph.add(new EndNode()); - LoopBeginNode loopBegin = currentGraph.add(new LoopBeginNode()); - lastInstr.setNext(preLoopEnd); - // Add the single non-loop predecessor of the loop header. - loopBegin.addForwardEnd(preLoopEnd); - lastInstr = loopBegin; - - // Create phi functions for all local variables and operand stack slots. - frameState.insertLoopPhis(loopBegin); - loopBegin.setStateAfter(frameState.create(block.startBci)); + private void synchronizedEpilogue(int bci, ValueNode returnValue) { + if (Modifier.isSynchronized(method.getModifiers())) { + MonitorExitNode monitorExit = genMonitorExit(methodSynchronizedObject, returnValue); + monitorExit.setStateAfter(frameState.create(bci)); + assert !frameState.rethrowException(); + } + } - // We have seen all forward branches. All subsequent backward branches will merge to the - // loop header. - // This ensures that the loop header has exactly one non-loop predecessor. - block.firstInstruction = loopBegin; - // We need to preserve the frame state builder of the loop header so that we can merge - // values for - // phi functions, so make a copy of it. - block.entryState = frameState.copy(); + private void createExceptionDispatch(ExceptionDispatchBlock block) { + assert frameState.stackSize() == 1 : frameState; + if (block.handler.isCatchAll()) { + assert block.successors.size() == 1; + appendGoto(createTarget(block.successors.get(0), frameState)); + return; + } - Debug.log(" created loop header %s", loopBegin); - } - assert lastInstr.next() == null : "instructions already appended at block " + block; - Debug.log(" frameState: %s", frameState); - - int endBCI = stream.endBCI(); - - stream.setBCI(block.startBci); - int bci = block.startBci; - BytecodesParsed.add(block.endBci - bci); - - while (bci < endBCI) { - if (graphBuilderConfig.eagerInfopointMode() && lnt != null) { - currentLineNumber = lnt.getLineNumber(bci); - if (currentLineNumber != previousLineNumber) { - append(new InfopointNode(InfopointReason.LINE_NUMBER, frameState.create(bci))); - previousLineNumber = currentLineNumber; + JavaType catchType = block.handler.getCatchType(); + if (graphBuilderConfig.eagerResolving()) { + catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF); + } + boolean initialized = (catchType instanceof ResolvedJavaType); + if (initialized && graphBuilderConfig.getSkippedExceptionTypes() != null) { + ResolvedJavaType resolvedCatchType = (ResolvedJavaType) catchType; + for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) { + if (skippedType.isAssignableFrom(resolvedCatchType)) { + append(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); + return; + } } } - // read the opcode - int opcode = stream.currentBC(); - traceState(); - traceInstruction(bci, opcode, bci == block.startBci); - if (bci == entryBCI) { - if (block.jsrScope != JsrScope.EMPTY_SCOPE) { - throw new BailoutException("OSR into a JSR scope is not supported"); - } - EntryMarkerNode x = append(new EntryMarkerNode()); - frameState.insertProxies(x); - x.setStateAfter(frameState.create(bci)); + ConstantNode typeInstruction = genTypeOrDeopt(Representation.ObjectHub, catchType, initialized); + if (typeInstruction != null) { + Block nextBlock = block.successors.size() == 1 ? unwindBlock(block.deoptBci) : block.successors.get(1); + ValueNode exception = frameState.stackAt(0); + CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null, false)); + frameState.apop(); + frameState.push(Kind.Object, checkCast); + FixedNode catchSuccessor = createTarget(block.successors.get(0), frameState); + frameState.apop(); + frameState.push(Kind.Object, exception); + FixedNode nextDispatch = createTarget(nextBlock, frameState); + checkCast.setNext(catchSuccessor); + append(new IfNode(currentGraph.unique(new InstanceOfNode((ResolvedJavaType) catchType, exception, null)), checkCast, nextDispatch, 0.5)); + } + } + + private void appendGoto(FixedNode target) { + if (lastInstr != null) { + lastInstr.setNext(target); } - processBytecode(bci, opcode); + } + + private static boolean isBlockEnd(Node n) { + return n instanceof ControlSplitNode || n instanceof ControlSinkNode; + } + + private void iterateBytecodesForBlock(Block block) { + if (block.isLoopHeader) { + // Create the loop header block, which later will merge the backward branches of the + // loop. + AbstractEndNode preLoopEnd = currentGraph.add(new EndNode()); + LoopBeginNode loopBegin = currentGraph.add(new LoopBeginNode()); + lastInstr.setNext(preLoopEnd); + // Add the single non-loop predecessor of the loop header. + loopBegin.addForwardEnd(preLoopEnd); + lastInstr = loopBegin; + + // Create phi functions for all local variables and operand stack slots. + frameState.insertLoopPhis(loopBegin); + loopBegin.setStateAfter(frameState.create(block.startBci)); + + /* + * We have seen all forward branches. All subsequent backward branches will merge to + * the loop header. This ensures that the loop header has exactly one non-loop + * predecessor. + */ + block.firstInstruction = loopBegin; + /* + * We need to preserve the frame state builder of the loop header so that we can + * merge values for phi functions, so make a copy of it. + */ + block.entryState = frameState.copy(); - if (lastInstr == null || isBlockEnd(lastInstr) || lastInstr.next() != null) { - break; + Debug.log(" created loop header %s", loopBegin); } + assert lastInstr.next() == null : "instructions already appended at block " + block; + Debug.log(" frameState: %s", frameState); - stream.next(); - bci = stream.currentBCI(); + int endBCI = stream.endBCI(); + + stream.setBCI(block.startBci); + int bci = block.startBci; + BytecodesParsed.add(block.endBci - bci); + + while (bci < endBCI) { + if (graphBuilderConfig.eagerInfopointMode() && lnt != null) { + currentLineNumber = lnt.getLineNumber(bci); + if (currentLineNumber != previousLineNumber) { + append(new InfopointNode(InfopointReason.LINE_NUMBER, frameState.create(bci))); + previousLineNumber = currentLineNumber; + } + } - if (bci > block.endBci) { - frameState.clearNonLiveLocals(currentBlock.localsLiveOut); - } - if (lastInstr instanceof StateSplit) { - if (lastInstr.getClass() == AbstractBeginNode.class) { - // BeginNodes do not need a frame state - } else { - StateSplit stateSplit = (StateSplit) lastInstr; - if (stateSplit.stateAfter() == null) { - stateSplit.setStateAfter(frameState.create(bci)); + // read the opcode + int opcode = stream.currentBC(); + traceState(); + traceInstruction(bci, opcode, bci == block.startBci); + if (bci == entryBCI) { + if (block.jsrScope != JsrScope.EMPTY_SCOPE) { + throw new BailoutException("OSR into a JSR scope is not supported"); + } + EntryMarkerNode x = append(new EntryMarkerNode()); + frameState.insertProxies(x); + x.setStateAfter(frameState.create(bci)); + } + processBytecode(bci, opcode); + + if (lastInstr == null || isBlockEnd(lastInstr) || lastInstr.next() != null) { + break; + } + + stream.next(); + bci = stream.currentBCI(); + + if (bci > block.endBci) { + frameState.clearNonLiveLocals(currentBlock.localsLiveOut); + } + if (lastInstr instanceof StateSplit) { + if (lastInstr.getClass() == AbstractBeginNode.class) { + // BeginNodes do not need a frame state + } else { + StateSplit stateSplit = (StateSplit) lastInstr; + if (stateSplit.stateAfter() == null) { + stateSplit.setStateAfter(frameState.create(bci)); + } + } + } + if (bci < endBCI) { + if (bci > block.endBci) { + assert !block.successors.get(0).isExceptionEntry; + assert block.numNormalSuccessors() == 1; + // we fell through to the next block, add a goto and break + appendGoto(createTarget(block.successors.get(0), frameState)); + break; } } } - if (bci < endBCI) { - if (bci > block.endBci) { - assert !block.successors.get(0).isExceptionEntry; - assert block.numNormalSuccessors() == 1; - // we fell through to the next block, add a goto and break - appendGoto(createTarget(block.successors.get(0), frameState)); - break; + } + + private final int traceLevel = Options.TraceBytecodeParserLevel.getValue(); + + private void traceState() { + if (traceLevel >= TRACELEVEL_STATE && Debug.isLogEnabled()) { + Debug.log(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method)); + for (int i = 0; i < frameState.localsSize(); ++i) { + ValueNode value = frameState.localAt(i); + Debug.log(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); + } + for (int i = 0; i < frameState.stackSize(); ++i) { + ValueNode value = frameState.stackAt(i); + Debug.log(String.format("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); } } } - } - - private final int traceLevel = Options.TraceBytecodeParserLevel.getValue(); - private void traceState() { - if (traceLevel >= TRACELEVEL_STATE && Debug.isLogEnabled()) { - Debug.log(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", frameState.localsSize(), frameState.stackSize(), method)); - for (int i = 0; i < frameState.localsSize(); ++i) { - ValueNode value = frameState.localAt(i); - Debug.log(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); - } - for (int i = 0; i < frameState.stackSize(); ++i) { - ValueNode value = frameState.stackAt(i); - Debug.log(String.format("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind().getJavaName(), value)); - } - } - } + private void processBytecode(int bci, int opcode) { + int cpi; - private void processBytecode(int bci, int opcode) { - int cpi; - - // Checkstyle: stop - // @formatter:off + // Checkstyle: stop + // @formatter:off switch (opcode) { case NOP : /* nothing to do */ break; case ACONST_NULL : frameState.apush(appendConstant(Constant.NULL_OBJECT)); break; @@ -2051,30 +2088,31 @@ throw new BailoutException("Unsupported opcode " + opcode + " (" + nameOf(opcode) + ") [bci=" + bci + "]"); } // @formatter:on - // Checkstyle: resume - } + // Checkstyle: resume + } - private void traceInstruction(int bci, int opcode, boolean blockStart) { - if (traceLevel >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { - StringBuilder sb = new StringBuilder(40); - sb.append(blockStart ? '+' : '|'); - if (bci < 10) { - sb.append(" "); - } else if (bci < 100) { - sb.append(' '); + private void traceInstruction(int bci, int opcode, boolean blockStart) { + if (traceLevel >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { + StringBuilder sb = new StringBuilder(40); + sb.append(blockStart ? '+' : '|'); + if (bci < 10) { + sb.append(" "); + } else if (bci < 100) { + sb.append(' '); + } + sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode)); + for (int i = bci + 1; i < stream.nextBCI(); ++i) { + sb.append(' ').append(stream.readUByte(i)); + } + if (!currentBlock.jsrScope.isEmpty()) { + sb.append(' ').append(currentBlock.jsrScope); + } + Debug.log(sb.toString()); } - sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode)); - for (int i = bci + 1; i < stream.nextBCI(); ++i) { - sb.append(' ').append(stream.readUByte(i)); - } - if (!currentBlock.jsrScope.isEmpty()) { - sb.append(' ').append(currentBlock.jsrScope); - } - Debug.log(sb.toString()); + } + + private void genArrayLength() { + frameState.ipush(append(new ArrayLengthNode(frameState.apop()))); } } - - private void genArrayLength() { - frameState.ipush(append(new ArrayLengthNode(frameState.apop()))); - } } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java Thu Jan 09 16:18:29 2014 +0100 @@ -66,7 +66,7 @@ ResolvedJavaMethod clinit = type.getClassInitializer(); if (clinit != null) { StructuredGraph graph = new StructuredGraph(clinit); - new GraphBuilderPhase(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); new VerifyOptionsPhase(type, metaAccess, option).apply(graph); } } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Thu Jan 09 16:18:29 2014 +0100 @@ -34,7 +34,6 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; public class CanonicalizerPhase extends BasePhase { @@ -102,11 +101,6 @@ new Instance(context, canonicalizeReads, workingSet, newNodesMark, customCanonicalizer).apply(graph, dumpGraph); } - @Deprecated - public void addToPhasePlan(PhasePlan plan, PhaseContext context) { - plan.addPhase(PhasePosition.AFTER_PARSING, new Instance(context, canonicalizeReads, customCanonicalizer)); - } - private static final class Instance extends Phase { private final Mark newNodesMark; diff -r 9267de45985b -r f4f0a8a01ce0 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 Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Thu Jan 09 16:18:29 2014 +0100 @@ -39,7 +39,6 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.options.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.InliningUtil.InlineInfo; import com.oracle.graal.phases.common.InliningUtil.Inlineable; import com.oracle.graal.phases.common.InliningUtil.InlineableGraph; @@ -294,8 +293,8 @@ private StructuredGraph parseBytecodes(StructuredGraph newGraph, HighTierContext context) { boolean hasMatureProfilingInfo = newGraph.method().getProfilingInfo().isMature(); - if (context.getPhasePlan() != null) { - context.getPhasePlan().runPhases(PhasePosition.AFTER_PARSING, newGraph); + if (context.getGraphBuilderSuite() != null) { + context.getGraphBuilderSuite().apply(newGraph, context); } assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING"; diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhasePlan.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhasePlan.java Thu Jan 09 14:31:31 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases; - -import java.util.*; - -import com.oracle.graal.nodes.*; - -/** - * Tells the compiler about additional phases that need to be executed during compilation. - */ -public class PhasePlan { - - // @formatter:off - /** - * The compilation is split into the following sections: - * ======================================================================== - * Period 1: High-level nodes. (Graph building) - * ======================================================================== - * Runtime-specific lowering. - * ======================================================================== - * Period 2: Mid-level nodes. (Memory dependence graph) - * ======================================================================== - * Target-specific lowering, de-SSA. - * ======================================================================== - * Period 3: Low-level nodes. (Register allocation, code generation) - * ======================================================================== - * - * A compiler extension phase can chose to run at the end of periods 1-3. - */ - public static enum PhasePosition { - AFTER_PARSING - } - // @formatter:on - - @SuppressWarnings("unchecked") private final ArrayList[] phases = new ArrayList[PhasePosition.values().length]; - - public void addPhase(PhasePosition pos, Phase phase) { - if (phases[pos.ordinal()] == null) { - phases[pos.ordinal()] = new ArrayList<>(); - } - phases[pos.ordinal()].add(phase); - } - - public void runPhases(PhasePosition pos, StructuredGraph graph) { - if (phases[pos.ordinal()] != null) { - for (Phase p : phases[pos.ordinal()]) { - p.apply(graph); - } - } - } -} diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java Thu Jan 09 16:18:29 2014 +0100 @@ -72,4 +72,10 @@ phase.apply(graph, context); } } + + public PhaseSuite copy() { + PhaseSuite suite = new PhaseSuite<>(); + suite.phases.addAll(phases); + return suite; + } } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java Thu Jan 09 16:18:29 2014 +0100 @@ -30,25 +30,25 @@ public class HighTierContext extends PhaseContext { - private final PhasePlan plan; + private final PhaseSuite graphBuilderSuite; private final GraphCache cache; private final OptimisticOptimizations optimisticOpts; public HighTierContext(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, LoweringProvider lowerer, Replacements replacements, Assumptions assumptions, - GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) { + GraphCache cache, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts) { super(metaAccess, constantReflection, lowerer, replacements, assumptions); - this.plan = plan; this.cache = cache; + this.graphBuilderSuite = graphBuilderSuite; this.optimisticOpts = optimisticOpts; } - public HighTierContext(Providers providers, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) { - this(providers.getMetaAccess(), providers.getConstantReflection(), providers.getLowerer(), providers.getReplacements(), assumptions, cache, plan, optimisticOpts); + public HighTierContext(Providers providers, Assumptions assumptions, GraphCache cache, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts) { + this(providers.getMetaAccess(), providers.getConstantReflection(), providers.getLowerer(), providers.getReplacements(), assumptions, cache, graphBuilderSuite, optimisticOpts); } - public PhasePlan getPhasePlan() { - return plan; + public PhaseSuite getGraphBuilderSuite() { + return graphBuilderSuite; } public GraphCache getGraphCache() { @@ -60,6 +60,6 @@ } public HighTierContext replaceAssumptions(Assumptions newAssumptions) { - return new HighTierContext(getMetaAccess(), getConstantReflection(), getLowerer(), getReplacements(), newAssumptions, getGraphCache(), getPhasePlan(), getOptimisticOptimizations()); + return new HighTierContext(getMetaAccess(), getConstantReflection(), getLowerer(), getReplacements(), newAssumptions, getGraphCache(), getGraphBuilderSuite(), getOptimisticOptimizations()); } } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/SuitesProvider.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/SuitesProvider.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/SuitesProvider.java Thu Jan 09 16:18:29 2014 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.phases.tiers; +import com.oracle.graal.phases.*; + public interface SuitesProvider { /** @@ -34,4 +36,10 @@ * {@link #getDefaultSuites default} suites. */ Suites createSuites(); + + /** + * Get the default phase suite for creating new graphs. + */ + PhaseSuite getDefaultGraphBuilderSuite(); + } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -45,9 +45,8 @@ protected StructuredGraph test(final String snippet) { try (Scope s = Debug.scope("MethodSubstitutionTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { StructuredGraph graph = parse(snippet); - PhasePlan phasePlan = getDefaultPhasePlan(); Assumptions assumptions = new Assumptions(true); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, phasePlan, OptimisticOptimizations.ALL); + HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); Debug.dump(graph, "Graph"); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); Debug.dump(graph, "Graph"); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Thu Jan 09 16:18:29 2014 +0100 @@ -363,7 +363,7 @@ final StructuredGraph graph = new StructuredGraph(methodToParse); try (Scope s = Debug.scope("buildInitialGraph", graph)) { MetaAccessProvider metaAccess = providers.getMetaAccess(); - new GraphBuilderPhase(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph); + new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph); new WordTypeVerificationPhase(metaAccess, target.wordKind).apply(graph); new WordTypeRewriterPhase(metaAccess, target.wordKind).apply(graph); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Thu Jan 09 16:18:29 2014 +0100 @@ -37,7 +37,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; @@ -160,7 +159,6 @@ new DeadCodeEliminationPhase().apply(graph); } - @SuppressWarnings("deprecation") protected StructuredGraph parseForComparison(final String methodName) { try (Scope s = Debug.scope("Truffle", new DebugDumpScope("Comparison: " + methodName))) { @@ -171,17 +169,15 @@ canonicalizer.apply(graph, context); // Additional inlining. - final PhasePlan plan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(getMetaAccess(), GraphBuilderConfiguration.getEagerDefault(), TruffleCompilerImpl.Optimizations); - plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - canonicalizer.addToPhasePlan(plan, context); - plan.addPhase(PhasePosition.AFTER_PARSING, new DeadCodeEliminationPhase()); + PhaseSuite graphBuilderSuite = getEagerGraphBuilderSuite(); + graphBuilderSuite.appendPhase(canonicalizer); + graphBuilderSuite.appendPhase(new DeadCodeEliminationPhase()); new ConvertDeoptimizeToGuardPhase().apply(graph); canonicalizer.apply(graph, context); new DeadCodeEliminationPhase().apply(graph); - HighTierContext highTierContext = new HighTierContext(getProviders(), assumptions, null, plan, OptimisticOptimizations.NONE); + HighTierContext highTierContext = new HighTierContext(getProviders(), assumptions, null, graphBuilderSuite, TruffleCompilerImpl.Optimizations); InliningPhase inliningPhase = new InliningPhase(canonicalizer); inliningPhase.apply(graph, highTierContext); removeFrameStates(graph); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Thu Jan 09 16:18:29 2014 +0100 @@ -42,7 +42,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; @@ -195,17 +194,16 @@ private static CompilationResult compileMethod(ResolvedJavaMethod javaMethod) { Providers providers = getGraalProviders(); MetaAccessProvider metaAccess = providers.getMetaAccess(); - Suites suites = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().createSuites(); + SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites(); + Suites suites = suitesProvider.createSuites(); suites.getHighTier().findPhase(InliningPhase.class).remove(); StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); - PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccess, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + new GraphBuilderPhase.Instance(metaAccess, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + PhaseSuite graphBuilderSuite = suitesProvider.getDefaultGraphBuilderSuite(); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); CompilationResultBuilderFactory factory = getOptimizedCallTargetInstrumentationFactory(backend.getTarget().arch.getName(), javaMethod); - return compileGraph(graph, cc, javaMethod, providers, backend, providers.getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, getProfilingInfo(graph), + return compileGraph(graph, cc, javaMethod, providers, backend, providers.getCodeCache().getTarget(), null, graphBuilderSuite, OptimisticOptimizations.ALL, getProfilingInfo(graph), new SpeculationLog(), suites, true, new CompilationResult(), factory); } diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Thu Jan 09 16:18:29 2014 +0100 @@ -104,7 +104,7 @@ final StructuredGraph graph = new StructuredGraph(executeHelperMethod); try (Scope s = Debug.scope("createGraph", graph)) { - new GraphBuilderPhase(providers.getMetaAccess(), config, TruffleCompilerImpl.Optimizations).apply(graph); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), config, TruffleCompilerImpl.Optimizations).apply(graph); // Replace thisNode with constant. LocalNode thisNode = graph.getLocal(0); @@ -142,9 +142,8 @@ } // Additional inlining. - final PhasePlan plan = new PhasePlan(); canonicalizer.apply(graph, baseContext); - HighTierContext tierContext = new HighTierContext(providers, assumptions, cache, plan, OptimisticOptimizations.NONE); + HighTierContext tierContext = new HighTierContext(providers, assumptions, cache, new PhaseSuite(), OptimisticOptimizations.NONE); for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) { Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage()); diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Thu Jan 09 16:18:29 2014 +0100 @@ -95,7 +95,7 @@ final StructuredGraph graph = new StructuredGraph(method); PhaseContext phaseContext = new PhaseContext(providers, new Assumptions(false)); - new GraphBuilderPhase(phaseContext.getMetaAccess(), config, optimisticOptimizations).apply(graph); + new GraphBuilderPhase.Instance(phaseContext.getMetaAccess(), config, optimisticOptimizations).apply(graph); for (LocalNode l : graph.getNodes(LocalNode.class)) { if (l.kind() == Kind.Object) { diff -r 9267de45985b -r f4f0a8a01ce0 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Thu Jan 09 14:31:31 2014 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Thu Jan 09 16:18:29 2014 +0100 @@ -46,7 +46,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.printer.*; @@ -81,7 +80,7 @@ this.backend = runtime.getHostBackend(); Replacements truffleReplacements = ((GraalTruffleRuntime) Truffle.getRuntime()).getReplacements(); this.providers = backend.getProviders().copyWith(truffleReplacements); - this.suites = backend.getSuites().createSuites(); + this.suites = backend.getSuites().getDefaultSuites(); this.skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess()); // Create compilation queue. @@ -209,9 +208,7 @@ } } - public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final Assumptions assumptions) { - final PhasePlan plan = createPhasePlan(config); - + public InstalledCode compileMethodHelper(StructuredGraph graph, GraphBuilderConfiguration config, Assumptions assumptions) { try (Scope s = Debug.scope("TruffleFinal")) { Debug.dump(graph, "After TruffleTier"); } catch (Throwable e) { @@ -223,8 +220,8 @@ CodeCacheProvider codeCache = providers.getCodeCache(); CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false); CompilationResult compilationResult = new CompilationResult(graph.method().toString()); - result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, plan, OptimisticOptimizations.ALL, getProfilingInfo(graph), new SpeculationLog(), suites, - false, compilationResult, CompilationResultBuilderFactory.Default); + result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), null, createGraphBuilderSuite(config), OptimisticOptimizations.ALL, getProfilingInfo(graph), + new SpeculationLog(), suites, false, compilationResult, CompilationResultBuilderFactory.Default); } catch (Throwable e) { throw Debug.handle(e); } @@ -262,11 +259,12 @@ return installedCode; } - private PhasePlan createPhasePlan(final GraphBuilderConfiguration config) { - final PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(providers.getMetaAccess(), config, TruffleCompilerImpl.Optimizations); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - return phasePlan; + private PhaseSuite createGraphBuilderSuite(GraphBuilderConfiguration config) { + PhaseSuite suite = backend.getSuites().getDefaultGraphBuilderSuite().copy(); + ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); + iterator.remove(); + iterator.add(new GraphBuilderPhase(config)); + return suite; } public void processAssumption(Assumptions newAssumptions, Assumption assumption, List manual) {