changeset 7064:8d16b9b2c51e

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