changeset 13585:f4f0a8a01ce0

remove PhasePlan
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 09 Jan 2014 16:18:29 +0100
parents 9267de45985b
children 7737fbb055b0
files graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILCompilationResult.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.java/src/com/oracle/graal/java/VerifyOptionsPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhasePlan.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/SuitesProvider.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java
diffstat 41 files changed, 1773 insertions(+), 1826 deletions(-) [+]
line wrap: on
line diff
--- 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<HighTierContext> 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();
 
--- 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) {
--- 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");
--- 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;
--- 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<HighTierContext> getDefaultGraphBuilderSuite() {
+        // defensive copying
+        return backend.getSuites().getDefaultGraphBuilderSuite().copy();
     }
 
-    protected PhasePlan getDefaultPhasePlan(boolean eagerInfopointMode) {
-        PhasePlan plan = new PhasePlan();
+    protected PhaseSuite<HighTierContext> 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<HighTierContext> suite = getDefaultGraphBuilderSuite().copy();
+        ListIterator<BasePhase<? super HighTierContext>> iterator = suite.findPhase(GraphBuilderPhase.class);
+        iterator.remove();
+        iterator.add(new GraphBuilderPhase(gbConf));
+        return suite;
     }
 
     protected Replacements getReplacements() {
--- 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()) {
--- 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);
--- 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);
--- 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);
--- 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) {
--- 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);
--- 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);
         }
--- 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);
--- 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);
     }
--- 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);
     }
 }
--- 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);
     }
--- 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<HighTierContext> 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);
--- 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 extends CompilationResult> 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<HighTierContext> 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<HighTierContext> 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();
 
--- 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<Node> 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<HighTierContext> 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());
--- 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);
         }
 
--- 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);
--- 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());
--- 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<HighTierContext> getGraphBuilderSuite(HotSpotProviders providers) {
+        PhaseSuite<HighTierContext> 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);
--- 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<HighTierContext> 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<HighTierContext> getDefaultGraphBuilderSuite() {
+        return defaultGraphBuilderSuite;
+    }
+
     public Suites createSuites() {
         Suites ret = Suites.createDefaultSuites();
 
@@ -63,4 +70,10 @@
 
         return ret;
     }
+
+    private static PhaseSuite<HighTierContext> createGraphBuilderSuite() {
+        PhaseSuite<HighTierContext> suite = new PhaseSuite<>();
+        suite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getDefault()));
+        return suite;
+    }
 }
--- 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")) {
--- 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<HighTierContext> 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);
     }
 }
--- 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<HighTierContext> {
 
     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_<n> 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_<n> 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<Integer, SuccessorInfo> 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<Block> 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<Integer, SuccessorInfo> 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<Block> 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 extends ControlSinkNode> 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 extends ControlSplitNode> 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 extends FixedWithNextNode> 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 extends FloatingNode> 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 extends ControlSinkNode> 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<Block> 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 extends ControlSplitNode> 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<Block>() {
 
-    protected <T extends FixedWithNextNode> 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 extends FloatingNode> 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<Block> 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<Block>() {
+                    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())));
-    }
 }
--- 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);
             }
         }
--- 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<PhaseContext> {
@@ -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;
--- 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";
 
--- 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<Phase>[] 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);
-            }
-        }
-    }
-}
--- 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<C> copy() {
+        PhaseSuite<C> suite = new PhaseSuite<>();
+        suite.phases.addAll(phases);
+        return suite;
+    }
 }
--- 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<HighTierContext> 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<HighTierContext> 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<HighTierContext> graphBuilderSuite, OptimisticOptimizations optimisticOpts) {
+        this(providers.getMetaAccess(), providers.getConstantReflection(), providers.getLowerer(), providers.getReplacements(), assumptions, cache, graphBuilderSuite, optimisticOpts);
     }
 
-    public PhasePlan getPhasePlan() {
-        return plan;
+    public PhaseSuite<HighTierContext> 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());
     }
 }
--- 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<HighTierContext> getDefaultGraphBuilderSuite();
+
 }
--- 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");
--- 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);
 
--- 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<HighTierContext> 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);
--- 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<HighTierContext> 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);
     }
 
--- 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<HighTierContext>(), OptimisticOptimizations.NONE);
 
             for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) {
                 Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage());
--- 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) {
--- 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<HighTierContext> createGraphBuilderSuite(GraphBuilderConfiguration config) {
+        PhaseSuite<HighTierContext> suite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
+        ListIterator<BasePhase<? super HighTierContext>> iterator = suite.findPhase(GraphBuilderPhase.class);
+        iterator.remove();
+        iterator.add(new GraphBuilderPhase(config));
+        return suite;
     }
 
     public void processAssumption(Assumptions newAssumptions, Assumption assumption, List<AssumptionValidAssumption> manual) {